var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __esm = (fn, res) => function __init() {
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};

// shared/schema.ts
var schema_exports = {};
__export(schema_exports, {
  analyticsData: () => analyticsData,
  badges: () => badges,
  insertAnalyticsDataSchema: () => insertAnalyticsDataSchema,
  insertBadgeSchema: () => insertBadgeSchema,
  insertGoogleUserSchema: () => insertGoogleUserSchema,
  insertLearningChallengeSchema: () => insertLearningChallengeSchema,
  insertLearningLessonSchema: () => insertLearningLessonSchema,
  insertLearningModuleSchema: () => insertLearningModuleSchema,
  insertLearningPathSchema: () => insertLearningPathSchema,
  insertModelComparisonsSchema: () => insertModelComparisonsSchema,
  insertPersonaSchema: () => insertPersonaSchema,
  insertPromptCommentSchema: () => insertPromptCommentSchema,
  insertPromptKnowledgeSchema: () => insertPromptKnowledgeSchema,
  insertPromptMetricsSchema: () => insertPromptMetricsSchema,
  insertPromptSchema: () => insertPromptSchema,
  insertTemplateSchema: () => insertTemplateSchema,
  insertUsageLogSchema: () => insertUsageLogSchema,
  insertUserBadgeSchema: () => insertUserBadgeSchema,
  insertUserCompletionSchema: () => insertUserCompletionSchema,
  insertUserProgressSchema: () => insertUserProgressSchema,
  insertUserSchema: () => insertUserSchema,
  insertUserUsageSchema: () => insertUserUsageSchema,
  learningChallenges: () => learningChallenges,
  learningLessons: () => learningLessons,
  learningModules: () => learningModules,
  learningPaths: () => learningPaths,
  modelComparisons: () => modelComparisons,
  personas: () => personas,
  promptComments: () => promptComments,
  promptKnowledge: () => promptKnowledge,
  promptMetrics: () => promptMetrics,
  prompts: () => prompts,
  templates: () => templates,
  usageLogs: () => usageLogs,
  userBadges: () => userBadges,
  userCompletions: () => userCompletions,
  userProgress: () => userProgress,
  userUsage: () => userUsage,
  users: () => users
});
import { pgTable, text, serial, integer, timestamp, jsonb, real, varchar, boolean, date } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
var users, prompts, templates, personas, promptKnowledge, promptMetrics, modelComparisons, promptComments, userUsage, usageLogs, analyticsData, learningPaths, learningModules, learningLessons, learningChallenges, userProgress, userCompletions, userBadges, badges, insertUserSchema, insertGoogleUserSchema, insertPromptSchema, insertTemplateSchema, insertPersonaSchema, insertPromptKnowledgeSchema, insertPromptMetricsSchema, insertModelComparisonsSchema, insertPromptCommentSchema, insertAnalyticsDataSchema, insertLearningPathSchema, insertLearningModuleSchema, insertLearningLessonSchema, insertLearningChallengeSchema, insertUserProgressSchema, insertUserCompletionSchema, insertBadgeSchema, insertUserBadgeSchema, insertUserUsageSchema, insertUsageLogSchema;
var init_schema = __esm({
  "shared/schema.ts"() {
    "use strict";
    users = pgTable("users", {
      id: serial("id").primaryKey(),
      username: text("username").notNull().unique(),
      password: text("password"),
      // Made nullable for social login
      email: text("email").notNull().unique(),
      createdAt: timestamp("created_at").defaultNow().notNull(),
      // Social login fields
      googleId: text("google_id").unique(),
      profilePicture: text("profile_picture"),
      authProvider: text("auth_provider").default("local"),
      // "local", "google", etc.
      // Stripe subscription fields
      stripeCustomerId: text("stripe_customer_id"),
      stripeSubscriptionId: text("stripe_subscription_id"),
      subscriptionStatus: text("subscription_status").default("inactive"),
      subscriptionTier: text("subscription_tier").default("free"),
      subscriptionExpiresAt: timestamp("subscription_expires_at")
    });
    prompts = pgTable("prompts", {
      id: serial("id").primaryKey(),
      userId: integer("user_id").references(() => users.id),
      prompt: text("prompt").notNull(),
      useCase: text("use_case").notNull(),
      settings: jsonb("settings").notNull(),
      isFavorite: integer("is_favorite").default(0).notNull(),
      isPublic: integer("is_public").default(0).notNull(),
      // Added for public library
      title: text("title"),
      // Optional title for public prompts
      description: text("description"),
      // Optional description for public prompts
      tags: text("tags").array(),
      // Optional tags for searching and filtering
      upvotes: integer("upvotes").default(0).notNull(),
      // For social voting
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    templates = pgTable("templates", {
      id: serial("id").primaryKey(),
      title: text("title").notNull(),
      description: text("description").notNull(),
      content: text("content").notNull(),
      category: text("category").notNull(),
      userId: integer("user_id").references(() => users.id),
      isPublic: integer("is_public").default(0).notNull(),
      uses: integer("uses").default(0).notNull(),
      rating: integer("rating").default(0),
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    personas = pgTable("personas", {
      id: serial("id").primaryKey(),
      name: text("name").notNull(),
      description: text("description").notNull(),
      role: text("role").notNull(),
      // The main role of the persona, e.g., "Academic Researcher", "Marketing Specialist"
      traits: text("traits").notNull(),
      // Key personality traits, e.g., "Analytical, Detail-oriented, Methodical"
      voice: text("voice").notNull(),
      // Writing style/tone, e.g., "Formal academic with technical terminology"
      examples: text("examples").notNull(),
      // Example phrases or writing snippets
      systemPrompt: text("system_prompt").notNull(),
      // The system prompt to use with this persona
      userId: integer("user_id").references(() => users.id),
      isPublic: integer("is_public").default(0).notNull(),
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    promptKnowledge = pgTable("prompt_knowledge", {
      id: serial("id").primaryKey(),
      title: text("title").notNull(),
      category: text("category").notNull(),
      // e.g., "Technique", "Pattern", "Strategy", "Best Practice"
      useCase: text("use_case").notNull(),
      // e.g., "Content", "Research", "Creative", "Technical"
      description: text("description").notNull(),
      example: text("example").notNull(),
      source: text("source").notNull(),
      // source of the knowledge, e.g., "AI Code Builders Guide", "Comprehensive Prompting Guide"
      tags: text("tags").array().notNull(),
      // tags for filtering and searching
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    promptMetrics = pgTable("prompt_metrics", {
      id: serial("id").primaryKey(),
      promptId: integer("prompt_id").references(() => prompts.id),
      userId: integer("user_id").references(() => users.id),
      model: varchar("model", { length: 50 }).notNull(),
      // e.g., "gpt-4o", "claude-3-7-sonnet"
      useCase: varchar("use_case", { length: 50 }).notNull(),
      // e.g., "content", "research", "technical"
      tokenCount: integer("token_count").notNull(),
      // Total tokens used
      responseTime: real("response_time").notNull(),
      // Time in seconds to generate response
      rating: integer("rating").default(0),
      // User rating from 1-5
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    modelComparisons = pgTable("model_comparisons", {
      id: serial("id").primaryKey(),
      promptId: integer("prompt_id").references(() => prompts.id),
      userId: integer("user_id").references(() => users.id),
      originalPrompt: text("original_prompt").notNull(),
      model1: varchar("model1", { length: 50 }).notNull(),
      model2: varchar("model2", { length: 50 }).notNull(),
      response1: text("response1").notNull(),
      response2: text("response2").notNull(),
      winningModel: varchar("winning_model", { length: 50 }),
      comparisonNotes: text("comparison_notes"),
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    promptComments = pgTable("prompt_comments", {
      id: serial("id").primaryKey(),
      promptId: integer("prompt_id").references(() => prompts.id).notNull(),
      userId: integer("user_id").references(() => users.id),
      username: text("username").notNull(),
      // Store username for display
      comment: text("comment").notNull(),
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    userUsage = pgTable("user_usage", {
      id: serial("id").primaryKey(),
      userId: integer("user_id").notNull(),
      promptsUsed: integer("prompts_used").notNull().default(0),
      promptsLimit: integer("prompts_limit").notNull().default(5),
      lastResetDate: date("last_reset_date").notNull().defaultNow(),
      nextResetDate: date("next_reset_date").notNull(),
      createdAt: timestamp("created_at").notNull().defaultNow(),
      updatedAt: timestamp("updated_at").notNull().defaultNow(),
      enhancedPromptsCount: integer("enhanced_prompts_count").notNull().default(0),
      generatedPersonasCount: integer("generated_personas_count").notNull().default(0)
    });
    usageLogs = pgTable("usage_logs", {
      id: serial("id").primaryKey(),
      userId: integer("user_id").references(() => users.id).notNull(),
      action: text("action").notNull(),
      // 'prompt_enhanced', 'persona_generated', etc.
      timestamp: timestamp("timestamp").defaultNow().notNull(),
      metadata: jsonb("metadata")
      // Optional additional data like model used, etc.
    });
    analyticsData = pgTable("analytics_data", {
      id: serial("id").primaryKey(),
      date: timestamp("date").notNull(),
      userId: integer("user_id").references(() => users.id),
      category: varchar("category", { length: 50 }).notNull(),
      // e.g., "model", "useCase", "persona"
      itemName: varchar("item_name", { length: 100 }).notNull(),
      // e.g., "gpt-4o", "content", "Academic Researcher"
      promptCount: integer("prompt_count").default(0).notNull(),
      avgTokens: real("avg_tokens").default(0).notNull(),
      avgResponseTime: real("avg_response_time").default(0).notNull(),
      avgRating: real("avg_rating").default(0).notNull(),
      updateCount: integer("update_count").default(0).notNull()
      // Number of times this aggregate has been updated
    });
    learningPaths = pgTable("learning_paths", {
      id: serial("id").primaryKey(),
      title: text("title").notNull(),
      description: text("description").notNull(),
      difficulty: varchar("difficulty", { length: 20 }).notNull(),
      // beginner, intermediate, advanced
      estimatedHours: integer("estimated_hours").notNull(),
      bannerImage: text("banner_image"),
      // URL to an image
      isActive: boolean("is_active").default(true).notNull(),
      order: integer("order").default(0).notNull(),
      // For ordering in the UI
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    learningModules = pgTable("learning_modules", {
      id: serial("id").primaryKey(),
      pathId: integer("path_id").references(() => learningPaths.id).notNull(),
      title: text("title").notNull(),
      description: text("description").notNull(),
      order: integer("order").default(0).notNull(),
      // Sequence within the path
      requiredPoints: integer("required_points").default(0).notNull(),
      // Points needed to unlock
      estimatedHours: integer("estimated_hours").notNull(),
      bannerImage: text("banner_image"),
      // URL to an image
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    learningLessons = pgTable("learning_lessons", {
      id: serial("id").primaryKey(),
      moduleId: integer("module_id").references(() => learningModules.id).notNull(),
      title: text("title").notNull(),
      description: text("description").notNull(),
      content: text("content").notNull(),
      // Rich text content of the lesson
      type: varchar("type", { length: 30 }).notNull(),
      // "theory", "practice", "challenge"
      order: integer("order").default(0).notNull(),
      pointsReward: integer("points_reward").default(10).notNull(),
      estimatedMinutes: integer("estimated_minutes").default(15).notNull(),
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    learningChallenges = pgTable("learning_challenges", {
      id: serial("id").primaryKey(),
      lessonId: integer("lesson_id").references(() => learningLessons.id).notNull(),
      title: text("title").notNull(),
      description: text("description").notNull(),
      prompt: text("prompt").notNull(),
      // The challenge prompt
      criteria: jsonb("criteria").notNull(),
      // Criteria for successful completion
      difficulty: integer("difficulty").default(1).notNull(),
      // 1-5 scale
      pointsReward: integer("points_reward").default(25).notNull(),
      timeLimit: integer("time_limit"),
      // Time limit in minutes, null for no limit
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    userProgress = pgTable("user_progress", {
      id: serial("id").primaryKey(),
      userId: integer("user_id").references(() => users.id).notNull(),
      pathId: integer("path_id").references(() => learningPaths.id).notNull(),
      currentModuleId: integer("current_module_id").references(() => learningModules.id),
      currentLessonId: integer("current_lesson_id").references(() => learningLessons.id),
      pointsEarned: integer("points_earned").default(0).notNull(),
      modulesCompleted: integer("modules_completed").default(0).notNull(),
      lessonsCompleted: integer("lessons_completed").default(0).notNull(),
      challengesCompleted: integer("challenges_completed").default(0).notNull(),
      // Changed to match actual database schema
      lastActivity: timestamp("last_activity", { mode: "date" }).defaultNow().notNull(),
      isCompleted: boolean("is_completed").default(false).notNull()
    });
    userCompletions = pgTable("user_completions", {
      id: serial("id").primaryKey(),
      userId: integer("user_id").references(() => users.id).notNull(),
      lessonId: integer("lesson_id").references(() => learningLessons.id),
      challengeId: integer("challenge_id").references(() => learningChallenges.id),
      pointsEarned: integer("points_earned").notNull(),
      completedAt: timestamp("completed_at").defaultNow().notNull(),
      userNotes: text("user_notes")
      // Optional notes from the user
    });
    userBadges = pgTable("user_badges", {
      id: serial("id").primaryKey(),
      userId: integer("user_id").references(() => users.id).notNull(),
      badgeId: integer("badge_id").references(() => badges.id).notNull(),
      awardedAt: timestamp("awarded_at").defaultNow().notNull(),
      displayed: boolean("displayed").default(true).notNull()
      // Whether to display on profile
    });
    badges = pgTable("badges", {
      id: serial("id").primaryKey(),
      name: text("name").notNull(),
      description: text("description").notNull(),
      category: varchar("category", { length: 30 }).notNull(),
      // achievement, skill, special
      tier: varchar("tier", { length: 20 }).notNull(),
      // bronze, silver, gold, platinum
      image: text("image").notNull(),
      // URL to badge image
      requirements: jsonb("requirements").notNull(),
      // JSON object with requirements
      pointsReward: integer("points_reward").default(50).notNull(),
      createdAt: timestamp("created_at").defaultNow().notNull()
    });
    insertUserSchema = createInsertSchema(users).omit({
      id: true,
      createdAt: true,
      googleId: true,
      // These will be set explicitly when needed
      profilePicture: true
    });
    insertGoogleUserSchema = createInsertSchema(users).omit({
      id: true,
      createdAt: true,
      password: true
      // Password not needed for Google auth
    });
    insertPromptSchema = createInsertSchema(prompts).omit({
      id: true,
      createdAt: true
    });
    insertTemplateSchema = createInsertSchema(templates).omit({
      id: true,
      createdAt: true,
      uses: true,
      rating: true
    });
    insertPersonaSchema = createInsertSchema(personas).omit({
      id: true,
      createdAt: true
    });
    insertPromptKnowledgeSchema = createInsertSchema(promptKnowledge).omit({
      id: true,
      createdAt: true
    });
    insertPromptMetricsSchema = createInsertSchema(promptMetrics).omit({
      id: true,
      createdAt: true
    });
    insertModelComparisonsSchema = createInsertSchema(modelComparisons).omit({
      id: true,
      createdAt: true
    });
    insertPromptCommentSchema = createInsertSchema(promptComments).omit({
      id: true,
      createdAt: true
    });
    insertAnalyticsDataSchema = createInsertSchema(analyticsData).omit({
      id: true
    });
    insertLearningPathSchema = createInsertSchema(learningPaths).omit({
      id: true,
      createdAt: true
    });
    insertLearningModuleSchema = createInsertSchema(learningModules).omit({
      id: true,
      createdAt: true
    });
    insertLearningLessonSchema = createInsertSchema(learningLessons).omit({
      id: true,
      createdAt: true
    });
    insertLearningChallengeSchema = createInsertSchema(learningChallenges).omit({
      id: true,
      createdAt: true
    });
    insertUserProgressSchema = createInsertSchema(userProgress).omit({
      id: true,
      lastActivity: true
    });
    insertUserCompletionSchema = createInsertSchema(userCompletions).omit({
      id: true,
      completedAt: true
    });
    insertBadgeSchema = createInsertSchema(badges).omit({
      id: true,
      createdAt: true
    });
    insertUserBadgeSchema = createInsertSchema(userBadges).omit({
      id: true,
      awardedAt: true
    });
    insertUserUsageSchema = createInsertSchema(userUsage).omit({
      id: true,
      createdAt: true,
      updatedAt: true
    });
    insertUsageLogSchema = createInsertSchema(usageLogs).omit({
      id: true
    });
  }
});

// server/db.ts
var db_exports = {};
__export(db_exports, {
  db: () => db,
  pool: () => pool
});
import { Pool, neonConfig } from "@neondatabase/serverless";
import { drizzle } from "drizzle-orm/neon-serverless";
import ws from "ws";
var pool, db;
var init_db = __esm({
  "server/db.ts"() {
    "use strict";
    init_schema();
    neonConfig.webSocketConstructor = ws;
    if (!process.env.DATABASE_URL) {
      throw new Error(
        "DATABASE_URL must be set. Did you forget to provision a database?"
      );
    }
    pool = new Pool({ connectionString: process.env.DATABASE_URL });
    db = drizzle({ client: pool, schema: schema_exports });
  }
});

// server/storage.ts
import { eq, and, or, like, desc } from "drizzle-orm";
var storage;
var init_storage = __esm({
  "server/storage.ts"() {
    "use strict";
    init_db();
    init_schema();
    storage = {
      // User operations
      async createUser(data) {
        const [user] = await db.insert(users).values(data).returning();
        return user;
      },
      async getUser(id) {
        const [user] = await db.select().from(users).where(eq(users.id, id));
        return user;
      },
      async getUserByEmail(email) {
        const [user] = await db.select().from(users).where(eq(users.email, email));
        return user;
      },
      async getUserByGoogleId(googleId) {
        const [user] = await db.select().from(users).where(eq(users.googleId, googleId));
        return user;
      },
      async updateUser(id, data) {
        const [user] = await db.update(users).set(data).where(eq(users.id, id)).returning();
        return user;
      },
      // Prompt operations
      async createPrompt(data) {
        const [prompt] = await db.insert(prompts).values(data).returning();
        return prompt;
      },
      async getPrompt(id) {
        const [prompt] = await db.select().from(prompts).where(eq(prompts.id, id));
        return prompt;
      },
      async updatePrompt(id, data) {
        const [prompt] = await db.update(prompts).set(data).where(eq(prompts.id, id)).returning();
        return prompt;
      },
      async getAllPrompts() {
        return await db.select().from(prompts).orderBy(desc(prompts.createdAt));
      },
      async getPublicPrompts() {
        return await db.select().from(prompts).where(eq(prompts.isPublic, 1)).orderBy(desc(prompts.createdAt));
      },
      async getUserPrompts(userId) {
        return await db.select().from(prompts).where(eq(prompts.userId, userId)).orderBy(desc(prompts.createdAt));
      },
      async searchPublicPrompts(query) {
        return await db.select().from(prompts).where(and(
          eq(prompts.isPublic, 1),
          or(
            like(prompts.originalPrompt, `%${query}%`),
            like(prompts.enhancedPrompt, `%${query}%`),
            like(prompts.title, `%${query}%`)
          )
        )).orderBy(desc(prompts.createdAt));
      },
      async upvotePrompt(id) {
        const [prompt] = await db.update(prompts).set({ upvotes: Number(prompts.upvotes) + 1 }).where(eq(prompts.id, id)).returning();
        return prompt;
      },
      // Template operations
      async createTemplate(data) {
        const [template] = await db.insert(templates).values(data).returning();
        return template;
      },
      async getTemplate(id) {
        const [template] = await db.select().from(templates).where(eq(templates.id, id));
        return template;
      },
      async getTemplates() {
        return await db.select().from(templates).orderBy(desc(templates.createdAt));
      },
      async updateTemplate(id, data) {
        const [template] = await db.update(templates).set(data).where(eq(templates.id, id)).returning();
        return template;
      },
      async deleteTemplate(id) {
        const result = await db.delete(templates).where(eq(templates.id, id));
        return (result.rowCount ?? 0) > 0;
      },
      async initializeTemplates(data) {
        if (data.length > 0) {
          await db.insert(templates).values(data);
        }
      },
      // Persona operations
      async createPersona(data) {
        const [persona] = await db.insert(personas).values(data).returning();
        return persona;
      },
      async getPersona(id) {
        const [persona] = await db.select().from(personas).where(eq(personas.id, id));
        return persona;
      },
      async getPublicPersonas() {
        return await db.select().from(personas).where(eq(personas.isPublic, 1)).orderBy(desc(personas.createdAt));
      },
      async getUserPersonas(userId) {
        return await db.select().from(personas).where(eq(personas.userId, userId)).orderBy(desc(personas.createdAt));
      },
      async updatePersona(id, data) {
        const [persona] = await db.update(personas).set(data).where(eq(personas.id, id)).returning();
        return persona;
      },
      async deletePersona(id) {
        const result = await db.delete(personas).where(eq(personas.id, id));
        return (result.rowCount ?? 0) > 0;
      },
      async initializePersonas(data) {
        if (data.length > 0) {
          await db.insert(personas).values(data);
        }
      },
      // Prompt Knowledge operations
      async createPromptKnowledge(data) {
        const [knowledge] = await db.insert(promptKnowledge).values(data).returning();
        return knowledge;
      },
      async getPromptKnowledge(id) {
        const [knowledge] = await db.select().from(promptKnowledge).where(eq(promptKnowledge.id, id));
        return knowledge;
      },
      async getPromptKnowledgeByCategory(category) {
        return await db.select().from(promptKnowledge).where(eq(promptKnowledge.category, category));
      },
      async getPromptKnowledgeByUseCase(useCase) {
        return await db.select().from(promptKnowledge).where(eq(promptKnowledge.useCase, useCase));
      },
      async getAllPromptKnowledge() {
        return await db.select().from(promptKnowledge);
      },
      async searchPromptKnowledge(query) {
        return await db.select().from(promptKnowledge).where(or(
          like(promptKnowledge.title, `%${query}%`),
          like(promptKnowledge.description, `%${query}%`)
        ));
      },
      async updatePromptKnowledge(id, data) {
        const [knowledge] = await db.update(promptKnowledge).set(data).where(eq(promptKnowledge.id, id)).returning();
        return knowledge;
      },
      async deletePromptKnowledge(id) {
        const result = await db.delete(promptKnowledge).where(eq(promptKnowledge.id, id));
        return (result.rowCount ?? 0) > 0;
      },
      async initializePromptKnowledge(data) {
        if (data.length > 0) {
          await db.insert(promptKnowledge).values(data);
        }
      },
      // Learning Path operations
      async getLearningPaths() {
        return await db.select().from(learningPaths);
      },
      async getLearningPath(id) {
        const [path3] = await db.select().from(learningPaths).where(eq(learningPaths.id, id));
        return path3;
      },
      async getLearningModules(pathId) {
        return await db.select().from(learningModules).where(eq(learningModules.pathId, pathId));
      },
      async getLearningModule(id) {
        const [module] = await db.select().from(learningModules).where(eq(learningModules.id, id));
        return module;
      },
      async getLearningLessons(moduleId) {
        return await db.select().from(learningLessons).where(eq(learningLessons.moduleId, moduleId));
      },
      async getLearningLesson(id) {
        const [lesson] = await db.select().from(learningLessons).where(eq(learningLessons.id, id));
        return lesson;
      },
      async getLearningChallenges(lessonId) {
        return await db.select().from(learningChallenges).where(eq(learningChallenges.lessonId, lessonId));
      },
      async getLearningChallenge(id) {
        const [challenge] = await db.select().from(learningChallenges).where(eq(learningChallenges.id, id));
        return challenge;
      },
      // User Progress operations
      async getUserProgress(userId, pathId) {
        const [progress] = await db.select().from(userProgress).where(and(
          eq(userProgress.userId, userId),
          eq(userProgress.pathId, pathId)
        ));
        return progress;
      },
      // Badge operations
      async getAllBadges() {
        return await db.select().from(badges);
      },
      async getUserBadges(userId) {
        return await db.select().from(userBadges).where(eq(userBadges.userId, userId));
      },
      // Comment operations
      async createPromptComment(data) {
        const [comment] = await db.insert(promptComments).values(data).returning();
        return comment;
      },
      async getPromptComments(promptId) {
        return await db.select().from(promptComments).where(eq(promptComments.promptId, promptId)).orderBy(desc(promptComments.createdAt));
      },
      async deletePromptComment(id) {
        const result = await db.delete(promptComments).where(eq(promptComments.id, id));
        return (result.rowCount ?? 0) > 0;
      },
      async initializePrompts(data) {
        if (data.length > 0) {
          await db.insert(prompts).values(data);
        }
      }
    };
  }
});

// server/init-learning-paths.ts
var init_learning_paths_exports = {};
__export(init_learning_paths_exports, {
  initializePromptEngineeringCourse: () => initializePromptEngineeringCourse
});
import { eq as eq4 } from "drizzle-orm";
async function initializePromptEngineeringCourse(storage2) {
  try {
    console.log("Checking for existing Prompt Engineering course");
    const existingPaths = await db.select().from(learningPaths).where(
      eq4(learningPaths.title, "From Beginner to Intermediate: LLM Prompt Engineering")
    );
    if (existingPaths.length > 0) {
      console.log("Prompt Engineering course already exists, skipping initialization");
      return {
        path: existingPaths[0],
        modules: [],
        lessons: [],
        challenges: []
      };
    }
    console.log("Creating new Prompt Engineering course");
    const pathResults = await db.insert(learningPaths).values({
      title: "From Beginner to Intermediate: LLM Prompt Engineering",
      description: "Master the art and science of crafting effective prompts for AI language models. This comprehensive course covers foundations, advanced techniques, iterative refinement, and real-world applications.",
      difficulty: "beginner-intermediate",
      estimatedHours: 8,
      bannerImage: "https://images.unsplash.com/photo-1676099677358-64a4734ea9c4?q=80&w=2800&auto=format&fit=crop",
      isActive: true,
      order: 1
    }).returning();
    const promptEngineeringPath = pathResults[0];
    const module1Results = await db.insert(learningModules).values({
      pathId: promptEngineeringPath.id,
      title: "Foundations of Effective Prompt Engineering",
      description: "Learn the core principles of effective prompt design, understand prompt components, and recognize differences across major LLM providers.",
      order: 1,
      requiredPoints: 0,
      estimatedHours: 2,
      bannerImage: "https://images.unsplash.com/photo-1617791160505-6f00504e3519?q=80&w=2940&auto=format&fit=crop"
    }).returning();
    const module2Results = await db.insert(learningModules).values({
      pathId: promptEngineeringPath.id,
      title: "Advanced Prompting Techniques",
      description: "Master zero-shot and few-shot prompting, chain-of-thought reasoning, persona-based prompting, and effective use of delimiters.",
      order: 2,
      requiredPoints: 75,
      estimatedHours: 2,
      bannerImage: "https://images.unsplash.com/photo-1655720033654-a4239dd42d10?q=80&w=2940&auto=format&fit=crop"
    }).returning();
    const module3Results = await db.insert(learningModules).values({
      pathId: promptEngineeringPath.id,
      title: "Iterative Refinement and Optimization",
      description: "Learn the art of prompt debugging, refinement, and testing for optimal results across different scenarios.",
      order: 3,
      requiredPoints: 150,
      estimatedHours: 2,
      bannerImage: "https://images.unsplash.com/photo-1688891982748-830800e5833f?q=80&w=2940&auto=format&fit=crop"
    }).returning();
    const module4Results = await db.insert(learningModules).values({
      pathId: promptEngineeringPath.id,
      title: "Real-World Applications and Integration",
      description: "Discover how to apply prompt engineering in various domains and create cohesive prompt systems for real-world applications.",
      order: 4,
      requiredPoints: 225,
      estimatedHours: 2,
      bannerImage: "https://images.unsplash.com/photo-1638571447486-ed5a87abcc4f?q=80&w=3032&auto=format&fit=crop"
    }).returning();
    const lesson1_1Results = await db.insert(learningLessons).values({
      moduleId: module1Results[0].id,
      title: "The Evolution of Prompt Engineering",
      description: "Understand how prompt engineering has developed from basic queries to a sophisticated discipline",
      content: "# The Evolution of Prompt Engineering\n\nPrompt engineering has evolved significantly since the introduction of modern LLMs. This lesson explores the historical context and development of the field.\n\n## Early Beginnings\n\nPrompt engineering started with simple query-response patterns but quickly evolved as language models became more sophisticated.\n\n## Key Milestones\n\n1. Basic instruction prompts\n2. Introduction of few-shot examples\n3. Development of chain-of-thought techniques\n4. Creation of specialized frameworks for different tasks\n\n## Current State\n\nToday, prompt engineering is recognized as a critical skill for effective AI utilization, with specialized techniques for different domains and use cases.",
      type: "theory",
      order: 1,
      pointsReward: 20,
      estimatedMinutes: 15
    }).returning();
    const lesson1_2Results = await db.insert(learningLessons).values({
      moduleId: module1Results[0].id,
      title: "Core Components of Effective Prompts",
      description: "Learn about the essential elements that make up well-structured, effective prompts",
      content: "# Core Components of Effective Prompts\n\nA well-crafted prompt consists of several key components that work together to generate the desired output.\n\n## Essential Elements\n\n1. **Clear Context**: Providing relevant background information\n2. **Specific Instructions**: Explicit directions on what to generate\n3. **Role Assignment**: Defining the AI's perspective or expertise\n4. **Format Specifications**: How the response should be structured\n5. **Examples**: Demonstrations of expected inputs and outputs\n\n## Balancing Components\n\nThe art of prompt engineering involves balancing these elements based on your specific needs.",
      type: "theory",
      order: 2,
      pointsReward: 25,
      estimatedMinutes: 20
    }).returning();
    const lesson2_1Results = await db.insert(learningLessons).values({
      moduleId: module2Results[0].id,
      title: "Zero-Shot and Few-Shot Prompting",
      description: "Master techniques for getting quality results with minimal examples",
      content: "# Zero-Shot and Few-Shot Prompting\n\nThese techniques allow language models to perform tasks with limited or no specific examples.\n\n## Zero-Shot Prompting\n\nZero-shot prompting involves asking the model to perform a task without any demonstrations. This relies on the model's pre-training knowledge.\n\n## Few-Shot Prompting\n\nFew-shot prompting provides the model with a small number of examples to guide its responses, improving accuracy for specialized tasks.\n\n## Practical Applications\n\nThese techniques are particularly useful when:\n- Working with new or uncommon tasks\n- You have limited examples to work with\n- Testing a model's capabilities quickly",
      type: "technique",
      order: 1,
      pointsReward: 30,
      estimatedMinutes: 25
    }).returning();
    const lesson2_2Results = await db.insert(learningLessons).values({
      moduleId: module2Results[0].id,
      title: "Chain-of-Thought Reasoning",
      description: "Learn how to guide AI through complex reasoning processes step by step",
      content: '# Chain-of-Thought Reasoning\n\nChain-of-Thought (CoT) is a prompting technique that encourages language models to break down complex problems into a series of intermediate steps.\n\n## Benefits of CoT\n\n- Improves accuracy on logical and mathematical tasks\n- Creates more transparent reasoning processes\n- Helps avoid common reasoning errors\n\n## Implementation Techniques\n\n1. **Explicit CoT**: Directly asking the model to "think step by step"\n2. **Demonstrated CoT**: Providing examples that show the reasoning process\n3. **Self-Consistency CoT**: Generating multiple reasoning paths and selecting the most consistent answer',
      type: "technique",
      order: 2,
      pointsReward: 30,
      estimatedMinutes: 25
    }).returning();
    const lesson3_1Results = await db.insert(learningLessons).values({
      moduleId: module3Results[0].id,
      title: "Prompt Debugging Strategies",
      description: "Learn systematic approaches to identify and fix issues in your prompts",
      content: "# Prompt Debugging Strategies\n\nWhen prompts don't produce the expected results, systematic debugging approaches can help identify and resolve issues.\n\n## Common Prompt Issues\n\n1. **Ambiguity**: Unclear or vague instructions\n2. **Conflicting Instructions**: Contradictory guidance\n3. **Inadequate Context**: Missing important information\n4. **Format Problems**: Unclear structure requirements\n\n## Debugging Process\n\n1. Isolate the problematic sections of your prompt\n2. Test variations to pinpoint specific issues\n3. Apply incremental improvements\n4. Document what works and what doesn't",
      type: "practical",
      order: 1,
      pointsReward: 35,
      estimatedMinutes: 30
    }).returning();
    const lesson3_2Results = await db.insert(learningLessons).values({
      moduleId: module3Results[0].id,
      title: "A/B Testing for Prompt Optimization",
      description: "Apply systematic testing methods to compare and improve different prompt variations",
      content: "# A/B Testing for Prompt Optimization\n\nSystematic testing allows you to compare different prompt variations and determine which performs best for your specific use case.\n\n## Setting Up Effective Tests\n\n1. Define clear success metrics\n2. Create controlled prompt variations\n3. Use consistent evaluation methods\n4. Collect sufficient samples for statistical significance\n\n## Analysis Techniques\n\n- Compare qualitative and quantitative metrics\n- Identify patterns across different prompt structures\n- Document findings for future prompt development",
      type: "practical",
      order: 2,
      pointsReward: 35,
      estimatedMinutes: 30
    }).returning();
    const lesson4_1Results = await db.insert(learningLessons).values({
      moduleId: module4Results[0].id,
      title: "Domain-Specific Prompt Engineering",
      description: "Learn how to customize prompts for specific industries and use cases",
      content: "# Domain-Specific Prompt Engineering\n\nDifferent domains require specialized prompt approaches to achieve optimal results.\n\n## Industry-Specific Considerations\n\n- **Healthcare**: Managing sensitive information and medical terminology\n- **Legal**: Ensuring precision and adherence to specific formats\n- **Creative**: Balancing guidance with creative freedom\n- **Technical**: Incorporating domain expertise and technical requirements\n\n## Adaptation Strategies\n\n1. Research domain-specific terminology and conventions\n2. Consult with subject matter experts\n3. Build domain-specific prompt libraries\n4. Develop evaluation criteria relevant to the domain",
      type: "application",
      order: 1,
      pointsReward: 40,
      estimatedMinutes: 35
    }).returning();
    const lesson4_2Results = await db.insert(learningLessons).values({
      moduleId: module4Results[0].id,
      title: "Building Comprehensive Prompt Systems",
      description: "Design interconnected prompt frameworks for complex applications",
      content: "# Building Comprehensive Prompt Systems\n\nComplex applications often require multiple interconnected prompts working together as a coherent system.\n\n## System Architecture\n\n1. **Input Processing**: Preparing and normalizing user inputs\n2. **Prompt Routing**: Directing queries to appropriate specialized prompts\n3. **Response Generation**: Creating the primary content\n4. **Post-Processing**: Refining and formatting the final output\n\n## Implementation Considerations\n\n- Establish consistent interfaces between system components\n- Create robust error handling and fallback mechanisms\n- Design for extensibility and maintenance\n- Implement feedback loops for continuous improvement",
      type: "application",
      order: 2,
      pointsReward: 40,
      estimatedMinutes: 35
    }).returning();
    await db.insert(learningChallenges).values({
      lessonId: lesson1_1Results[0].id,
      title: "Prompt Evolution Analysis",
      description: "Analyze and compare different generations of prompts",
      prompt: "Analyze these three prompts and explain how they represent different stages of prompt engineering evolution: 1) 'Write about climate change' 2) 'Write a 500-word article about climate change impacts on agriculture' 3) 'As an environmental scientist specializing in agricultural impacts, write a structured 500-word analysis of climate change effects on crop yields in temperate regions. Include data trends, adaptation strategies, and future projections.'",
      criteria: JSON.stringify([
        { type: "contains", rule: "evolution stages", points: 10 },
        { type: "contains", rule: "specificity analysis", points: 10 },
        { type: "contains", rule: "improvement suggestions", points: 10 }
      ]),
      difficulty: 2,
      pointsReward: 30
    });
    await db.insert(learningChallenges).values({
      lessonId: lesson2_1Results[0].id,
      title: "Few-Shot Prompt Construction",
      description: "Create an effective few-shot prompt for a specialized task",
      prompt: "Create a few-shot prompt to teach an AI to generate fictional but scientifically plausible alien species descriptions. Include 2-3 examples in your prompt that demonstrate the desired format and content.",
      criteria: JSON.stringify([
        { type: "contains", rule: "clear instruction", points: 5 },
        { type: "contains", rule: "example format", points: 10 },
        { type: "contains", rule: "consistent pattern", points: 10 },
        { type: "length", rule: "300", points: 5 }
      ]),
      difficulty: 3,
      pointsReward: 40
    });
    await db.insert(learningChallenges).values({
      lessonId: lesson3_1Results[0].id,
      title: "Prompt Debugging Exercise",
      description: "Identify and fix issues in a problematic prompt",
      prompt: "This prompt has multiple issues: 'create content that's engaging but also professional while being comprehensive yet concise and include all important details without being too lengthy make it appropriate for beginners and experts.' Identify at least three specific problems with this prompt and provide a corrected version that resolves these issues.",
      criteria: JSON.stringify([
        { type: "contains", rule: "problem identification", points: 15 },
        { type: "contains", rule: "solution implementation", points: 15 },
        { type: "contains", rule: "improved structure", points: 10 }
      ]),
      difficulty: 3,
      pointsReward: 40
    });
    await db.insert(learningChallenges).values({
      lessonId: lesson4_1Results[0].id,
      title: "Domain-Specific Prompt Development",
      description: "Create a specialized prompt for a specific industry",
      prompt: "Develop a detailed prompt for generating financial investment advice. Your prompt should include appropriate disclaimers, ensure balanced perspective, require specific information inputs, and produce structured, professional output suitable for financial advisors to review before sharing with clients.",
      criteria: JSON.stringify([
        { type: "contains", rule: "domain terminology", points: 10 },
        { type: "contains", rule: "appropriate disclaimers", points: 10 },
        { type: "contains", rule: "structured format", points: 10 },
        { type: "contains", rule: "information requirements", points: 10 }
      ]),
      difficulty: 4,
      pointsReward: 50
    });
    await db.insert(badges).values({
      name: "Prompt Engineer",
      description: "Completed the full Prompt Engineering course with at least 80% success rate",
      image: "https://images.unsplash.com/photo-1617791160505-6f00504e3519?h=100&w=100&fit=crop",
      category: "achievement",
      tier: "gold",
      requirements: JSON.stringify({
        coursesCompleted: ["prompt-engineering"],
        minimumScore: 80
      }),
      pointsReward: 300
    });
    console.log("Successfully created Prompt Engineering course");
    return {
      path: promptEngineeringPath,
      modules: [module1Results[0], module2Results[0], module3Results[0], module4Results[0]],
      lessons: [
        lesson1_1Results[0],
        lesson1_2Results[0],
        lesson2_1Results[0],
        lesson2_2Results[0],
        lesson3_1Results[0],
        lesson3_2Results[0],
        lesson4_1Results[0],
        lesson4_2Results[0]
      ],
      challenges: []
    };
  } catch (error) {
    console.error("Error initializing Prompt Engineering course:", error);
    throw error;
  }
}
var init_init_learning_paths = __esm({
  "server/init-learning-paths.ts"() {
    "use strict";
    init_db();
    init_schema();
  }
});

// server/services/direct-api.ts
var direct_api_exports = {};
__export(direct_api_exports, {
  enhancePromptDirect: () => enhancePromptDirect
});
import { OpenAI } from "openai";
var enhancePromptDirect;
var init_direct_api = __esm({
  "server/services/direct-api.ts"() {
    "use strict";
    init_storage();
    enhancePromptDirect = async (originalPrompt, useCase, settings) => {
      if (!process.env.OPENROUTER_API_KEY) {
        throw new Error("OPENROUTER_API_KEY environment variable is not set");
      }
      try {
        console.log("Enhancing prompt with direct API access. Settings:", JSON.stringify(settings, null, 2));
        let model = "meta-llama/llama-3-70b-instruct";
        if (settings.model === "claude") {
          model = "anthropic/claude-3-7-sonnet-20250219";
        } else if (settings.model === "mistral") {
          model = "mistralai/mistral-7b-instruct";
        } else if (settings.model === "gemini") {
          model = "google/gemini-1.5-pro-latest";
        }
        const temperature = settings.creativity === "high" ? 0.9 : settings.creativity === "medium" ? 0.7 : 0.4;
        let personaInfo = "";
        if (settings.personaId) {
          try {
            const persona = await storage.getPersona(settings.personaId);
            if (persona) {
              personaInfo = `PERSONA CHARACTERISTICS:
- Name: ${persona.name}
- Role: ${persona.role}
- Voice: ${persona.voice}
- Traits: ${persona.traits}`;
            }
          } catch (error) {
            console.error("Error fetching persona:", error);
          }
        }
        const personaInstruction = settings.personaId ? "Additionally, follow the persona's voice, traits, and style to create a prompt that reflects their specific character and approach." : "";
        let frameworkInstructions = "";
        if (settings.framework === "r-costar") {
          frameworkInstructions = `
FRAMEWORK: Use the R-COSTAR structure:
- Role: Define a specific role for the AI to assume
- Context: Include relevant background information
- Objective: Clearly state the goal or desired outcome
- Style: Specify the writing style or format approach
- Tone: Use a ${settings.tone} tone as specified
- Audience: Identify the target audience or end users
- Response: Define the expected format of the response`;
        } else if (settings.framework === "crispe") {
          frameworkInstructions = `
FRAMEWORK: Use the CRISPE structure:
- Capacity: Define the AI's role and capabilities
- Role: Specify the role the AI should take
- Insight: Provide essential background knowledge
- Specific: Include clear, detailed instructions
- Process: Outline the steps or methodology
- Example: Include an example of the desired output`;
        } else if (settings.framework === "tag") {
          frameworkInstructions = `
FRAMEWORK: Use the TAG structure:
- Task: Clearly define the specific task to be performed
- Action: Outline the precise actions required
- Goal: State the desired outcome or objective`;
        } else if (settings.framework === "pep") {
          frameworkInstructions = `
FRAMEWORK: Use the PEP structure:
- Purpose: Define the clear purpose or objective
- Example: Provide an illustrative example
- Persona: Specify the character or voice to use`;
        } else if (settings.framework === "ethos") {
          frameworkInstructions = `
FRAMEWORK: Use the ETHOS structure:
- Expertise: Define the expertise or knowledge domain required
- Task: Specify the precise task to be performed
- How: Provide methodology or approach guidelines
- Outcome: Clearly state the desired outcome
- Setup: Include any contextual setup or constraints`;
        } else {
          frameworkInstructions = `
ENHANCEMENT APPROACH:
- Add clear, logical structure with distinct sections
- Make all instructions specific and actionable
- Include contextual details relevant to ${useCase}
- Ensure all expectations and requirements are explicit`;
        }
        const systemMessage = `You are an expert prompt engineer who specializes in crafting highly effective prompts for advanced AI models. Your expertise is in transforming basic prompts into powerful, detailed instructions that produce exceptional results.

TASK: Transform the user's prompt into a more effective version by adding structure, specificity, and clarity.

${useCase === "image-generation" && settings.artisticStyle ? `SPECIAL INSTRUCTION: This is for image generation. You MUST emphasize the ${settings.artisticStyle} artistic style throughout the enhanced prompt. Include specific visual elements characteristic of this style.` : ""}

${personaInfo}

${frameworkInstructions}

ENHANCEMENT GUIDELINES:
1. Preserve the original intent and core topic completely
2. Optimize specifically for ${useCase} use case
3. Use a ${settings.tone} tone throughout
4. Make the prompt ${settings.format === "detailed" ? "comprehensive with logical sections" : "concise yet comprehensive"}
5. Include clear instructions about expected format, scope and detail level
6. Add relevant contextual information that would help the AI understand the request better
7. Where appropriate, use specific examples
${personaInstruction}

FORMAT REQUIREMENTS (CRITICAL - FOLLOW EXACTLY):
- Return ONLY the enhanced prompt text with NO introduction, explanation, or commentary
- NO headings like "Enhanced Prompt:" or section titles
- NO markdown formatting of any kind
- NO numbered or bulleted lists of improvements
- NO leading or trailing formatting marks
- NO apologies or explanations about your approach
- NEVER explain the changes you made
- BEGIN your response with the first word of the enhanced prompt`;
        const openai = new OpenAI({
          apiKey: process.env.OPENROUTER_API_KEY,
          baseURL: "https://openrouter.ai/api/v1",
          defaultHeaders: {
            "HTTP-Referer": "https://replit.app",
            "X-Title": "Enhance My Prompt"
          }
        });
        const response = await openai.chat.completions.create({
          model,
          messages: [
            {
              role: "system",
              content: systemMessage
            },
            {
              role: "user",
              content: `Please enhance this prompt for a ${useCase} use case${useCase === "image-generation" && settings.artisticStyle ? ` in ${settings.artisticStyle} style` : ""}:

${originalPrompt}`
            }
          ],
          temperature,
          max_tokens: 2048
        });
        let enhancedPrompt = response.choices[0]?.message.content || originalPrompt;
        enhancedPrompt = enhancedPrompt.trim();
        const defaultImprovements = [
          "Improved structure and clarity",
          "Added more specific details",
          "Optimized for the selected use case"
        ];
        return {
          enhancedPrompt,
          improvements: defaultImprovements,
          direct: true
          // Flag to indicate direct model access was used
        };
      } catch (error) {
        console.error("Error enhancing prompt with direct API access:", error);
        throw error;
      }
    };
  }
});

// server/usage-limits.ts
var usage_limits_exports = {};
__export(usage_limits_exports, {
  getRemainingPrompts: () => getRemainingPrompts,
  getUserUsage: () => getUserUsage,
  hasReachedPromptLimit: () => hasReachedPromptLimit,
  recordPromptUsage: () => recordPromptUsage
});
import { eq as eq5 } from "drizzle-orm";
async function getUserUsage(userId) {
  try {
    const [existingUsage] = await db.select().from(userUsage).where(eq5(userUsage.userId, userId));
    const today = /* @__PURE__ */ new Date();
    const nextResetDate = new Date(today.getFullYear(), today.getMonth() + 1, 1);
    if (existingUsage) {
      return {
        ...existingUsage,
        nextResetDate: nextResetDate.toISOString()
      };
    }
    try {
      const [newUsage] = await db.insert(userUsage).values({
        userId,
        promptsUsed: 0,
        promptsLimit: 5,
        lastResetDate: today,
        nextResetDate,
        createdAt: /* @__PURE__ */ new Date(),
        updatedAt: /* @__PURE__ */ new Date(),
        enhancedPromptsCount: 0,
        generatedPersonasCount: 0
      }).returning();
      return {
        ...newUsage,
        nextResetDate: nextResetDate.toISOString()
      };
    } catch (insertError) {
      console.error(`Error creating usage record for user ${userId}:`, insertError);
      throw new Error("Failed to create usage record");
    }
  } catch (error) {
    console.error(`Error in getUserUsage for user ${userId}:`, error);
    throw error;
  }
}
async function hasReachedPromptLimit(userId) {
  try {
    const usage = await getUserUsage(userId);
    const [user] = await db.select().from(users).where(eq5(users.id, userId));
    if (!user) {
      console.error(`User ${userId} not found when checking prompt limit`);
      throw new Error("User not found");
    }
    if (user.subscriptionTier !== "free") {
      return false;
    }
    return usage.promptsUsed >= FREE_TIER_LIMIT;
  } catch (error) {
    console.error(`Error checking prompt limit for user ${userId}:`, error);
    return true;
  }
}
async function recordPromptUsage(userId) {
  try {
    const usage = await getUserUsage(userId);
    const [user] = await db.select().from(users).where(eq5(users.id, userId));
    if (!user) {
      console.error(`User ${userId} not found when recording prompt usage`);
      throw new Error("User not found");
    }
    if (user.subscriptionTier !== "free") {
      return true;
    }
    if (usage.promptsUsed >= FREE_TIER_LIMIT) {
      return false;
    }
    try {
      await db.update(userUsage).set({
        promptsUsed: usage.promptsUsed + 1,
        updatedAt: /* @__PURE__ */ new Date()
      }).where(eq5(userUsage.userId, userId));
      return true;
    } catch (updateError) {
      console.error(`Error updating usage count for user ${userId}:`, updateError);
      throw new Error("Failed to update usage count");
    }
  } catch (error) {
    console.error(`Error recording prompt usage for user ${userId}:`, error);
    return false;
  }
}
async function getRemainingPrompts(userId) {
  try {
    const usage = await getUserUsage(userId);
    const [user] = await db.select().from(users).where(eq5(users.id, userId));
    if (!user) {
      console.error(`User ${userId} not found when getting remaining prompts`);
      throw new Error("User not found");
    }
    const isUnlimited = user.subscriptionTier !== "free";
    const limit = isUnlimited ? Infinity : FREE_TIER_LIMIT;
    const used = usage.promptsUsed;
    const remaining = isUnlimited ? Infinity : Math.max(0, limit - used);
    return {
      used,
      limit,
      remaining,
      nextResetDate: usage.nextResetDate,
      isUnlimited
    };
  } catch (error) {
    console.error(`Error getting remaining prompts for user ${userId}:`, error);
    const today = /* @__PURE__ */ new Date();
    const nextResetDate = new Date(today.getFullYear(), today.getMonth() + 1, 1);
    return {
      used: 0,
      limit: FREE_TIER_LIMIT,
      remaining: FREE_TIER_LIMIT,
      nextResetDate: nextResetDate.toISOString(),
      isUnlimited: false
    };
  }
}
var FREE_TIER_LIMIT;
var init_usage_limits = __esm({
  "server/usage-limits.ts"() {
    "use strict";
    init_db();
    init_schema();
    FREE_TIER_LIMIT = 5;
  }
});

// server/migrations/add-missing-usage-columns.ts
var add_missing_usage_columns_exports = {};
__export(add_missing_usage_columns_exports, {
  addMissingUsageColumns: () => addMissingUsageColumns
});
import { sql as sql2 } from "drizzle-orm";
async function addMissingUsageColumns() {
  try {
    const columnCheckResult = await db.execute(sql2`
      SELECT column_name 
      FROM information_schema.columns
      WHERE table_name = 'user_usage' AND column_name = 'enhanced_prompts_count'
    `);
    if (columnCheckResult.rows.length === 0) {
      console.log("Adding missing enhanced_prompts_count column to user_usage table");
      await db.execute(sql2`
        ALTER TABLE user_usage 
        ADD COLUMN IF NOT EXISTS enhanced_prompts_count INTEGER NOT NULL DEFAULT 0
      `);
    } else {
      console.log("Column enhanced_prompts_count already exists");
    }
    const personasColumnCheck = await db.execute(sql2`
      SELECT column_name 
      FROM information_schema.columns
      WHERE table_name = 'user_usage' AND column_name = 'generated_personas_count'
    `);
    if (personasColumnCheck.rows.length === 0) {
      console.log("Adding missing generated_personas_count column to user_usage table");
      await db.execute(sql2`
        ALTER TABLE user_usage 
        ADD COLUMN IF NOT EXISTS generated_personas_count INTEGER NOT NULL DEFAULT 0
      `);
    } else {
      console.log("Column generated_personas_count already exists");
    }
    console.log("Migration completed successfully");
    return true;
  } catch (error) {
    console.error("Migration failed:", error);
    return false;
  }
}
var init_add_missing_usage_columns = __esm({
  "server/migrations/add-missing-usage-columns.ts"() {
    "use strict";
    init_db();
  }
});

// server/index.ts
import express3 from "express";

// server/routes.ts
init_storage();
init_db();
init_schema();
import { createServer } from "http";
import Stripe2 from "stripe";
import { z as z2 } from "zod";
import { eq as eq6 } from "drizzle-orm";

// server/services/gemini.ts
init_storage();
import { GoogleGenerativeAI, HarmCategory, HarmBlockThreshold } from "@google/generative-ai";
if (!process.env.GEMINI_API_KEY) {
  console.warn("GEMINI_API_KEY is not set. Gemini AI features will fall back to templates.");
}
var createGenAIClient = () => {
  try {
    return new GoogleGenerativeAI(process.env.GEMINI_API_KEY || "dummy-key");
  } catch (error) {
    console.error("Error initializing Gemini AI client:", error);
    return {
      getGenerativeModel: () => ({
        generateContent: () => Promise.reject(new Error("Gemini client initialization failed"))
      })
    };
  }
};
var genAI = createGenAIClient();
var safetySettings = [
  {
    category: HarmCategory.HARM_CATEGORY_HARASSMENT,
    threshold: HarmBlockThreshold.BLOCK_ONLY_HIGH
  },
  {
    category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
    threshold: HarmBlockThreshold.BLOCK_ONLY_HIGH
  },
  {
    category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
    threshold: HarmBlockThreshold.BLOCK_ONLY_HIGH
  },
  {
    category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
    threshold: HarmBlockThreshold.BLOCK_ONLY_HIGH
  }
];
var GEMINI_MODELS = {
  PRO: "gemini-1.5-pro-latest",
  // Using the latest Gemini Pro model
  PRO_VISION: "gemini-1.5-pro-vision-latest"
  // Using the latest Gemini Pro Vision model
};
var getRelevantPromptKnowledge = async (useCase) => {
  try {
    const knowledgeEntries = await storage.getPromptKnowledgeByUseCase(useCase);
    const allEntries = knowledgeEntries.length > 0 ? knowledgeEntries : await storage.getAllPromptKnowledge();
    if (allEntries.length === 0) {
      return "";
    }
    let formattedKnowledge = "PROMPT TECHNIQUES AND BEST PRACTICES:\n\n";
    const limitedEntries = allEntries.slice(0, 3);
    limitedEntries.forEach((entry, index) => {
      formattedKnowledge += `${index + 1}. ${entry.title}: ${entry.description}
`;
      formattedKnowledge += `   Example: ${entry.example}

`;
    });
    return formattedKnowledge;
  } catch (error) {
    console.error("Error getting prompt knowledge:", error);
    return "";
  }
};
var getPersonaInfo = async (personaId) => {
  if (!personaId) return "";
  try {
    const persona = await storage.getPersona(personaId);
    if (!persona) return "";
    return `
PERSONA CONTEXT:
Name: ${persona.name}
Role: ${persona.role}
Voice: ${persona.voice}
Traits: ${persona.traits}
System Prompt: ${persona.systemPrompt}
    `;
  } catch (error) {
    console.error("Error fetching persona:", error);
    return "";
  }
};
var createGeminiPrompt = async (originalPrompt, useCase, settings) => {
  const creativityLevel = {
    "low": "be conservative and follow standard formats",
    "medium": "be moderately creative while maintaining clarity",
    "high": "be highly creative and innovative"
  }[settings.creativity] || "be moderately creative while maintaining clarity";
  let useCaseGuidance = "";
  switch (useCase) {
    case "content":
      useCaseGuidance = "for content creation, focusing on engaging and SEO-friendly structure";
      break;
    case "research":
      useCaseGuidance = "for academic or professional research, focusing on thoroughness and methodological rigor";
      break;
    case "creative":
      useCaseGuidance = "for creative writing, focusing on narrative elements and emotional impact";
      break;
    case "technical":
      useCaseGuidance = "for technical documentation, focusing on clarity, accuracy, and comprehensive coverage";
      break;
    case "image-generation":
      const artisticStyle = settings.artisticStyle ? `in ${settings.artisticStyle} style` : "";
      useCaseGuidance = `for image generation prompts ${artisticStyle}, focusing on visual details, style specifications, composition, lighting, mood, and technical parameters`;
      break;
    default:
      useCaseGuidance = "with a balanced approach suitable for general purposes";
  }
  const knowledgeGuidance = await getRelevantPromptKnowledge(useCase);
  const personaGuidance = await getPersonaInfo(settings.personaId);
  const personaInstruction = settings.personaId ? "Apply the persona's voice, traits, and style to create a prompt that reflects their specific character and approach." : "";
  let frameworkInstructions = "";
  if (settings.framework === "r-costar") {
    frameworkInstructions = `
Structure the prompt following the R-COSTAR framework:
- Role: Define the specific role the AI should assume
- Context: Provide relevant background information
- Objective: Clearly state the goal or desired outcome
- Style: Specify the writing style or approach
- Tone: Use a ${settings.tone} tone
- Audience: Identify the target audience or end users
- Response: Define the expected format of the response`;
  } else if (settings.framework === "crispe") {
    frameworkInstructions = `
Structure the prompt following the CRISPE framework:
- Capacity: Define the AI's role and capabilities
- Role: Specify the role the AI should take
- Insight: Provide essential background knowledge
- Specific: Include clear, detailed instructions
- Process: Outline the steps or methodology
- Example: Include an example of the desired output`;
  } else if (settings.framework === "tag") {
    frameworkInstructions = `
Structure the prompt following the TAG framework:
- Task: Clearly define the specific task to be performed
- Action: Outline the precise actions required
- Goal: State the desired outcome or objective`;
  } else if (settings.framework === "pep") {
    frameworkInstructions = `
Structure the prompt following the PEP framework:
- Purpose: Define the clear purpose or objective
- Example: Provide an illustrative example
- Persona: Specify the character or voice to use`;
  } else if (settings.framework === "ethos") {
    frameworkInstructions = `
Structure the prompt following the ETHOS framework:
- Expertise: Define the expertise or knowledge domain required
- Task: Specify the precise task to be performed
- How: Provide methodology or approach guidelines
- Outcome: Clearly state the desired outcome
- Setup: Include any contextual setup or constraints`;
  } else {
    frameworkInstructions = `
Enhance this prompt with:
- Clear structure and instructions
- Specific objectives and expected outcomes
- Step-by-step organization for complex requests
- [PLACEHOLDERS] for customizable variables`;
  }
  return `
Task: Enhance the following prompt for an AI system.

Original prompt:
"${originalPrompt}"

${knowledgeGuidance}
${personaGuidance}

Enhance this prompt ${useCaseGuidance}${useCase === "image-generation" && settings.artisticStyle ? ` with an emphasis on ${settings.artisticStyle} artistic style` : ""}.
Use a ${settings.tone} tone.
Format in ${settings.format}.
${creativityLevel}.
${personaInstruction}

${frameworkInstructions}

IMPORTANT FORMATTING INSTRUCTIONS:
1. Do NOT use markdown formatting in your response.
2. Do NOT include headings like "Enhanced Prompt:" or numbered sections.
3. Do NOT include a section on improvements or key changes.
4. Start your response immediately with the enhanced prompt text.
5. Do NOT include any leading or trailing formatting marks like --- or \`\`\`
`;
};
var parseGeminiResponse = (responseText) => {
  try {
    let enhancedPrompt = responseText;
    let improvements = ["Enhanced the original prompt"];
    const improvementSectionRegex = /(?:\n\n|\r\n\r\n)(?:\d+\.\s+)?(?:\*\*)?(?:key improvements|improvements|three key improvements|key changes|enhancements)(?:\*\*)?(?:\s*:|:?\s*\n)[\s\S]*/i;
    enhancedPrompt = enhancedPrompt.replace(improvementSectionRegex, "");
    const headers = [
      /^\d+\.\s+\*\*Enhanced Prompt:\*\*\s*/i,
      /^## \d+\. Enhanced Prompt:\s*/i,
      /^## Enhanced Prompt:\s*/i,
      /^# Enhanced Prompt:\s*/i,
      /^Enhanced Prompt:\s*/i,
      /^Improved Prompt:\s*/i,
      /^Prompt:\s*/i
    ];
    for (const headerRegex of headers) {
      const match = enhancedPrompt.match(headerRegex);
      if (match) {
        enhancedPrompt = enhancedPrompt.replace(match[0], "");
        break;
      }
    }
    enhancedPrompt = enhancedPrompt.replace(/\*\*/g, "").replace(/^#{1,6}\s+/gm, "").replace(/`/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").trim();
    return {
      enhancedPrompt,
      improvements
    };
  } catch (error) {
    console.error("Error parsing Gemini response:", error);
    return {
      enhancedPrompt: responseText,
      improvements: ["Enhanced the original prompt"]
    };
  }
};
var getUseCaseTemplate = (useCase, settings) => {
  settings = settings || {};
  const useCaseTemplates = {
    "content": "I need you to act as a professional content strategist with expertise in digital marketing. Create a comprehensive outline for a blog post about [TOPIC]. The blog should target [AUDIENCE] who are interested in [INTEREST]. Include SEO keywords, recommended headings (H2, H3), estimated word count per section, and suggestions for visual elements. The tone should be [TONE] and the goal is to [GOAL].",
    "research": "I need a detailed research analysis on [TOPIC]. Please include: 1) Historical context and evolution, 2) Current state and leading theories, 3) Key debates and controversies, 4) Future directions and emerging trends, 5) Practical applications in [FIELD], and 6) Comprehensive bibliography of seminal works. Focus especially on peer-reviewed research from the last 5 years.",
    "creative": "Create a compelling short story in the [GENRE] genre with the following elements: a protagonist who is [CHARACTER TRAIT], a setting that involves [SETTING], and a central conflict about [CONFLICT]. The story should have an unexpected twist and convey the theme of [THEME]. Use vivid sensory details and varied sentence structure. Aim for approximately 1000 words with a clear beginning, middle, and end.",
    "technical": "Create comprehensive technical documentation for [TECHNOLOGY/PRODUCT]. Include: 1) Overview and architecture, 2) Installation requirements and procedure, 3) Configuration options with examples, 4) API endpoints with request/response formats, 5) Common error codes and troubleshooting, 6) Security best practices, and 7) Performance optimization guidelines. Use clear, concise language appropriate for developers with intermediate experience.",
    "image-generation": `Create a detailed and highly descriptive prompt for generating an image of [SUBJECT]${settings.artisticStyle ? ` in ${settings.artisticStyle} style` : ""}. Please include: 1) Specific visual characteristics (colors, textures, lighting, perspective), 2) Style specifications (focusing on ${settings.artisticStyle || "appropriate artistic style"}), 3) Spatial relationships and composition (foreground, background, positioning), 4) Emotional tone or mood to convey, 5) Details about setting or environment, and 6) Any technical parameters (aspect ratio, resolution quality, rendering style). Use vivid, visual language that clearly communicates the desired outcome.`
  };
  return useCaseTemplates[useCase] || "Create a detailed prompt about [TOPIC] with specific instructions, structure, and clear goals.";
};
var enhanceWithTimeout = async (model, prompt, timeoutMs = 3e4) => {
  const timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => reject(new Error("Request timed out")), timeoutMs);
  });
  try {
    const apiCallPromise = model.generateContent(prompt).then((result) => {
      if (!result || !result.response) {
        throw new Error("Invalid response from Gemini API");
      }
      return result.response.text();
    });
    return await Promise.race([apiCallPromise, timeoutPromise]);
  } catch (error) {
    console.error("Error in API call:", error);
    throw error;
  }
};
var enhancePromptWithGemini = async (originalPrompt, useCase, settings) => {
  try {
    const modelId = settings.model === "gemini" ? GEMINI_MODELS.PRO : GEMINI_MODELS.PRO;
    const model = genAI.getGenerativeModel({
      model: modelId,
      safetySettings,
      generationConfig: {
        temperature: settings.creativity === "high" ? 0.8 : settings.creativity === "medium" ? 0.5 : 0.3,
        topP: 0.95,
        topK: 64,
        maxOutputTokens: 2048
        // Increased token limit for more comprehensive templates
      }
    });
    const prompt = await createGeminiPrompt(originalPrompt, useCase, settings);
    try {
      const text2 = await enhanceWithTimeout(model, prompt, 3e4);
      return parseGeminiResponse(text2);
    } catch (apiError) {
      console.error("API call to Gemini failed or timed out:", apiError);
      const templatePrompt = getUseCaseTemplate(useCase, settings);
      return {
        enhancedPrompt: templatePrompt,
        improvements: [
          "Added specific structure with clear sections",
          "Included placeholders for key variables that you should customize",
          "Enhanced specificity with numbered lists and clear organization"
        ]
      };
    }
  } catch (error) {
    console.error("Error enhancing prompt with Gemini:", error);
    const templatePrompt = getUseCaseTemplate(useCase, settings);
    return {
      enhancedPrompt: templatePrompt,
      improvements: [
        "Added specific structure with clear sections",
        "Included placeholders for key variables that you should customize",
        "Enhanced specificity with numbered lists and clear organization"
      ]
    };
  }
};

// server/services/openrouter.ts
init_storage();
import fetch from "node-fetch";
var OPENROUTER_MODELS = {
  ANTHROPIC: "anthropic/claude-3-7-sonnet-20250219",
  // Updated to the latest Claude model released February 2025
  MISTRAL: "mistralai/mistral-7b-instruct",
  LLAMA: "meta-llama/llama-3-70b-instruct",
  GEMINI: "google/gemini-1.5-pro-latest"
};
var getPersonaInfo2 = async (personaId) => {
  if (!personaId) return "";
  try {
    const persona = await storage.getPersona(personaId);
    if (!persona) return "";
    return `
PERSONA CONTEXT:
Name: ${persona.name}
Role: ${persona.role}
Voice: ${persona.voice}
Traits: ${persona.traits}
System Prompt: ${persona.systemPrompt}
    `;
  } catch (error) {
    console.error("Error fetching persona:", error);
    return "";
  }
};
var createOpenRouterPrompt = async (originalPrompt, useCase, settings) => {
  const personaInfo = await getPersonaInfo2(settings.personaId);
  const personaInstruction = settings.personaId ? "Additionally, follow the persona's voice, traits, and style to create a prompt that reflects their specific character and approach." : "";
  let frameworkInstructions = "";
  if (settings.framework === "r-costar") {
    frameworkInstructions = `
Apply the R-COSTAR framework to structure the prompt:
- Role: Define a specific role for the AI to assume
- Context: Include relevant background information
- Objective: Clearly state the goal or desired outcome
- Style: Specify the writing style or format approach
- Tone: Use a ${settings.tone} tone as specified
- Audience: Identify the target audience or end users
- Response: Define the expected format of the response`;
  } else if (settings.framework === "crispe") {
    frameworkInstructions = `
Apply the CRISPE framework to structure the prompt:
- Capacity: Define the AI's role and capabilities
- Role: Specify the role the AI should take
- Insight: Provide essential background knowledge
- Specific: Include clear, detailed instructions
- Process: Outline the steps or methodology
- Example: Include an example of the desired output`;
  } else if (settings.framework === "tag") {
    frameworkInstructions = `
Apply the TAG framework to structure the prompt:
- Task: Clearly define the specific task to be performed
- Action: Outline the precise actions required
- Goal: State the desired outcome or objective`;
  } else if (settings.framework === "pep") {
    frameworkInstructions = `
Apply the PEP framework to structure the prompt:
- Purpose: Define the clear purpose or objective
- Example: Provide an illustrative example
- Persona: Specify the character or voice to use`;
  } else if (settings.framework === "ethos") {
    frameworkInstructions = `
Apply the ETHOS framework to structure the prompt:
- Expertise: Define the expertise or knowledge domain required
- Task: Specify the precise task to be performed
- How: Provide methodology or approach guidelines
- Outcome: Clearly state the desired outcome
- Setup: Include any contextual setup or constraints`;
  } else {
    frameworkInstructions = `
General enhancement guidelines:
- Add clear structure and organization
- Incorporate specificity and details
- Include relevant context and precise instructions
- Make instructions actionable and clear`;
  }
  const systemMessage = `You are an expert prompt engineer who specializes in crafting highly effective prompts for advanced AI models. Your expertise is in transforming basic prompts into powerful, detailed instructions that produce exceptional results.

TASK: Transform the user's prompt into a more effective version by adding structure, specificity, and clarity.

${useCase === "image-generation" && settings.artisticStyle ? `SPECIAL INSTRUCTION: This is for image generation. You MUST emphasize the ${settings.artisticStyle} artistic style throughout the enhanced prompt. Include specific visual elements characteristic of this style.` : ""}

${personaInfo}

${frameworkInstructions}

ENHANCEMENT GUIDELINES:
1. Preserve the original intent and core topic completely
2. Optimize specifically for ${useCase} use case
3. Use a ${settings.tone} tone throughout
4. Make the prompt ${settings.format === "detailed" ? "comprehensive with logical sections" : "concise yet comprehensive"}
5. Include clear instructions about expected format, scope and detail level
6. Add relevant contextual information that would help the AI understand the request better
7. Where appropriate, use specific examples
${personaInstruction}

FORMAT REQUIREMENTS (CRITICAL - FOLLOW EXACTLY):
- Return ONLY the enhanced prompt text with NO introduction, explanation, or commentary
- NO headings like "Enhanced Prompt:" or section titles
- NO markdown formatting of any kind
- NO numbered or bulleted lists of improvements
- NO leading or trailing formatting marks
- NO apologies or explanations about your approach
- NEVER explain the changes you made
- BEGIN your response with the first word of the enhanced prompt`;
  let userMessage = `Please enhance this prompt for a ${useCase} use case`;
  if (useCase === "image-generation" && settings.artisticStyle) {
    userMessage += ` in ${settings.artisticStyle} style`;
  }
  userMessage += `:

${originalPrompt}`;
  return JSON.stringify({
    system: systemMessage,
    prompt: userMessage
  });
};
var parseOpenRouterResponse = (responseText) => {
  try {
    let enhancedPrompt = responseText.trim();
    const improvementSectionRegex = /(?:\n\n|\r\n\r\n)(?:\d+\.\s+)?(?:\*\*)?(?:key improvements|improvements|three key improvements|key changes|enhancements)(?:\*\*)?(?:\s*:|:?\s*\n)[\s\S]*/i;
    enhancedPrompt = enhancedPrompt.replace(improvementSectionRegex, "");
    const headers = [
      /^\d+\.\s+\*\*Enhanced Prompt:\*\*\s*/i,
      /^## \d+\. Enhanced Prompt:\s*/i,
      /^## Enhanced Prompt:\s*/i,
      /^# Enhanced Prompt:\s*/i,
      /^Enhanced Prompt:\s*/i,
      /^Improved Prompt:\s*/i,
      /^Prompt:\s*/i
    ];
    for (const headerRegex of headers) {
      const match = enhancedPrompt.match(headerRegex);
      if (match) {
        enhancedPrompt = enhancedPrompt.replace(match[0], "");
        break;
      }
    }
    enhancedPrompt = enhancedPrompt.replace(/\*\*/g, "").replace(/^#{1,6}\s+/gm, "").replace(/`/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/---/g, "").trim();
    const defaultImprovements = [
      "Improved structure and clarity",
      "Added more specific details",
      "Optimized for the selected use case"
    ];
    return {
      enhancedPrompt,
      improvements: defaultImprovements
    };
  } catch (error) {
    console.error("Error parsing Open Router response:", error);
    return {
      enhancedPrompt: responseText,
      improvements: ["Improved structure and clarity", "Added more specific details", "Optimized for the selected use case"]
    };
  }
};
var enhancePromptWithOpenRouter = async (originalPrompt, useCase, settings) => {
  if (!process.env.OPENROUTER_API_KEY) {
    throw new Error("OPENROUTER_API_KEY environment variable is not set");
  }
  try {
    let model = OPENROUTER_MODELS.MISTRAL;
    if (settings.model === "claude") {
      model = OPENROUTER_MODELS.ANTHROPIC;
    } else if (settings.model === "llama") {
      model = OPENROUTER_MODELS.LLAMA;
    } else if (settings.model === "gemini") {
      model = OPENROUTER_MODELS.GEMINI;
    }
    const temperature = settings.creativity === "high" ? 0.9 : settings.creativity === "medium" ? 0.7 : 0.4;
    const prompt = await createOpenRouterPrompt(originalPrompt, useCase, settings);
    const fetchWithTimeout = async (url, options, timeoutMs) => {
      const controller = new AbortController();
      const { signal } = controller;
      const timeout = setTimeout(() => controller.abort(), timeoutMs);
      try {
        const response2 = await fetch(url, {
          ...options,
          signal
        });
        clearTimeout(timeout);
        return response2;
      } catch (error) {
        clearTimeout(timeout);
        throw error;
      }
    };
    const personaInfo = await getPersonaInfo2(settings.personaId);
    const personaInstruction = settings.personaId ? "Additionally, follow the persona's voice, traits, and style to create a prompt that reflects their specific character and approach." : "";
    const response = await fetchWithTimeout("https://openrouter.ai/api/v1/chat/completions", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${process.env.OPENROUTER_API_KEY}`,
        "HTTP-Referer": "https://replit.app",
        // Replace with your actual domain
        "X-Title": "Enhance My Prompt"
        // Your app name
      },
      body: JSON.stringify({
        model,
        messages: [
          {
            role: "system",
            content: `You are an expert prompt engineer who specializes in crafting highly effective prompts for advanced AI models. Your expertise is in transforming basic prompts into powerful, detailed instructions that produce exceptional results.

TASK: Transform the user's prompt into a more effective version by adding structure, specificity, and clarity.

${useCase === "image-generation" && settings.artisticStyle ? `SPECIAL INSTRUCTION: This is for image generation. You MUST emphasize the ${settings.artisticStyle} artistic style throughout the enhanced prompt. Include specific visual elements characteristic of this style.` : ""}

${personaInfo}

${settings.framework === "r-costar" ? `
FRAMEWORK: Use the R-COSTAR structure:
- Role: Define a specific role for the AI to assume
- Context: Include relevant background information
- Objective: Clearly state the goal or desired outcome
- Style: Specify the writing style or format approach
- Tone: Use a ${settings.tone} tone as specified
- Audience: Identify the target audience or end users
- Response: Define the expected format of the response` : settings.framework === "crispe" ? `
FRAMEWORK: Use the CRISPE structure:
- Capacity: Define the AI's role and capabilities
- Role: Specify the role the AI should take
- Insight: Provide essential background knowledge
- Specific: Include clear, detailed instructions
- Process: Outline the steps or methodology
- Example: Include an example of the desired output` : settings.framework === "tag" ? `
FRAMEWORK: Use the TAG structure:
- Task: Clearly define the specific task to be performed
- Action: Outline the precise actions required
- Goal: State the desired outcome or objective` : settings.framework === "pep" ? `
FRAMEWORK: Use the PEP structure:
- Purpose: Define the clear purpose or objective
- Example: Provide an illustrative example
- Persona: Specify the character or voice to use` : settings.framework === "ethos" ? `
FRAMEWORK: Use the ETHOS structure:
- Expertise: Define the expertise or knowledge domain required
- Task: Specify the precise task to be performed
- How: Provide methodology or approach guidelines
- Outcome: Clearly state the desired outcome
- Setup: Include any contextual setup or constraints` : `
ENHANCEMENT APPROACH:
- Add clear, logical structure with distinct sections
- Make all instructions specific and actionable
- Include contextual details relevant to ${useCase}
- Ensure all expectations and requirements are explicit`}

ENHANCEMENT GUIDELINES:
1. Preserve the original intent and core topic completely
2. Optimize specifically for ${useCase} use case
3. Use a ${settings.tone} tone throughout
4. Make the prompt ${settings.format === "detailed" ? "comprehensive with logical sections" : "concise yet comprehensive"}
5. Include clear instructions about expected format, scope and detail level
6. Add relevant contextual information that would help the AI understand the request better
7. Where appropriate, use specific examples
${personaInstruction}

FORMAT REQUIREMENTS (CRITICAL - FOLLOW EXACTLY):
- Return ONLY the enhanced prompt text with NO introduction, explanation, or commentary
- NO headings like "Enhanced Prompt:" or section titles
- NO markdown formatting of any kind
- NO numbered or bulleted lists of improvements
- NO leading or trailing formatting marks
- NO apologies or explanations about your approach
- NEVER explain the changes you made
- BEGIN your response with the first word of the enhanced prompt`
          },
          {
            role: "user",
            content: `Please enhance this prompt for a ${useCase} use case${useCase === "image-generation" && settings.artisticStyle ? ` in ${settings.artisticStyle} style` : ""}:

${originalPrompt}`
          }
        ],
        temperature,
        max_tokens: 2048
        // Increased token limit for more comprehensive templates
      })
    }, 3e4);
    if (!response.ok) {
      const errorText = await response.text();
      console.error("Open Router API error:", errorText);
      throw new Error(`Open Router API error: ${response.status} ${response.statusText}`);
    }
    const data = await response.json();
    if (!data.choices || data.choices.length === 0) {
      throw new Error("Invalid response from Open Router API");
    }
    const content = data.choices[0].message.content;
    return parseOpenRouterResponse(content);
  } catch (error) {
    console.error("Error enhancing prompt with Open Router:", error);
    throw error;
  }
};

// server/services/personaGenerator.ts
import { GoogleGenerativeAI as GoogleGenerativeAI2 } from "@google/generative-ai";
import fetch2 from "node-fetch";
var generatePersonaWithGemini = async (input) => {
  try {
    if (!process.env.GEMINI_API_KEY) {
      throw new Error("GEMINI_API_KEY is not set");
    }
    const genAI2 = new GoogleGenerativeAI2(process.env.GEMINI_API_KEY);
    const model = genAI2.getGenerativeModel({ model: "gemini-1.5-pro-latest" });
    const primaryUseCase = input.primaryUseCase || "general purpose";
    const tone = input.tone || "neutral";
    const prompt = `
Generate a detailed AI persona based on the following concept: "${input.concept}".
This persona will be used for: ${primaryUseCase}.
The tone should be: ${tone}.

Format the response as a JSON object with the following fields:
{
  "name": "A concise, memorable name for this persona",
  "description": "A concise description of this persona (2-3 sentences max)",
  "role": "The professional or character role this persona embodies",
  "traits": "3-5 key personality traits, separated by commas",
  "voice": "A detailed description of the communication style (1-2 sentences)",
  "examples": "3 short example phrases or responses this persona would typically say",
  "systemPrompt": "A comprehensive system prompt (2-3 paragraphs) that could be given to an AI system to embody this persona"
}

Make sure all fields are appropriate for the concept and use case. Focus on creating a distinct, memorable personality.
`;
    const result = await model.generateContent(prompt);
    const text2 = result.response.text();
    try {
      let jsonText = text2;
      if (text2.includes("```json")) {
        jsonText = text2.split("```json")[1].split("```")[0].trim();
      } else if (text2.includes("```")) {
        jsonText = text2.split("```")[1].split("```")[0].trim();
      }
      const parsedResponse = JSON.parse(jsonText);
      return parsedResponse;
    } catch (parseError) {
      console.error("Error parsing Gemini JSON response:", parseError);
      console.log("Raw response:", text2);
      throw new Error("Failed to parse AI response. Please try again.");
    }
  } catch (error) {
    console.error("Error generating persona with Gemini:", error);
    throw new Error(`Failed to generate persona: ${error.message || "Unknown error"}`);
  }
};
var generatePersonaWithOpenRouter = async (input) => {
  try {
    if (!process.env.OPENROUTER_API_KEY) {
      throw new Error("OPENROUTER_API_KEY is not set");
    }
    const modelId = input.openRouterModel || OPENROUTER_MODELS.ANTHROPIC;
    const primaryUseCase = input.primaryUseCase || "general purpose";
    const tone = input.tone || "neutral";
    const systemPrompt = `You are a professional AI persona creator. Your task is to generate a detailed, well-crafted persona based on the user's request. The persona should be suitable for use in an AI system. Make sure all content is appropriate and professional.`;
    const userPrompt = `
Generate a detailed AI persona based on the following concept: "${input.concept}".
This persona will be used for: ${primaryUseCase}.
The tone should be: ${tone}.

Format the response as a JSON object with the following fields and nothing else:
{
  "name": "A concise, memorable name for this persona",
  "description": "A concise description of this persona (2-3 sentences max)",
  "role": "The professional or character role this persona embodies",
  "traits": "3-5 key personality traits, separated by commas",
  "voice": "A detailed description of the communication style (1-2 sentences)",
  "examples": "3 short example phrases or responses this persona would typically say",
  "systemPrompt": "A comprehensive system prompt (2-3 paragraphs) that could be given to an AI system to embody this persona"
}

The response should ONLY contain valid JSON, no markdown formatting or explanations.
`;
    const response = await fetch2("https://openrouter.ai/api/v1/chat/completions", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${process.env.OPENROUTER_API_KEY}`,
        "HTTP-Referer": "https://replit.com",
        "X-Title": "Prompt Engineering Tool"
      },
      body: JSON.stringify({
        model: modelId,
        messages: [
          { role: "system", content: systemPrompt },
          { role: "user", content: userPrompt }
        ],
        temperature: 0.7,
        response_format: { type: "json_object" }
      })
    });
    if (!response.ok) {
      const errorData = await response.text();
      console.error("OpenRouter API error:", errorData);
      throw new Error(`OpenRouter API error: ${response.status}`);
    }
    const data = await response.json();
    const resultText = data.choices[0]?.message?.content || "";
    try {
      let jsonText = resultText;
      if (resultText.includes("```json")) {
        jsonText = resultText.split("```json")[1].split("```")[0].trim();
      } else if (resultText.includes("```")) {
        jsonText = resultText.split("```")[1].split("```")[0].trim();
      }
      const parsedResponse = JSON.parse(jsonText);
      return parsedResponse;
    } catch (parseError) {
      console.error("Error parsing OpenRouter response:", parseError);
      console.log("Raw response:", resultText);
      throw new Error("Failed to parse AI response. Please try again.");
    }
  } catch (error) {
    console.error("Error generating persona with OpenRouter:", error);
    throw new Error(`Failed to generate persona: ${error.message || "Unknown error"}`);
  }
};
var generatePersona = async (input) => {
  try {
    if (input.model === "gemini") {
      return await generatePersonaWithGemini(input);
    } else {
      return await generatePersonaWithOpenRouter(input);
    }
  } catch (error) {
    console.error("Error in persona generation:", error);
    try {
      console.log(`Falling back to ${input.model === "gemini" ? "OpenRouter" : "Gemini"} for persona generation`);
      if (input.model === "gemini") {
        return await generatePersonaWithOpenRouter(input);
      } else {
        return await generatePersonaWithGemini(input);
      }
    } catch (fallbackError) {
      console.error("Fallback persona generation also failed:", fallbackError);
      throw new Error("Failed to generate persona with all available models. Please try again later.");
    }
  }
};
var getPersonaTemplates = () => {
  return {
    "Professional": [
      {
        name: "Technical Expert",
        role: "Software engineer and technical consultant",
        description: "A seasoned technology professional with deep expertise in software development and architecture.",
        traits: "Analytical, Detail-oriented, Problem-solver, Methodical",
        voice: "Clear, technical, and precise communication style with a focus on accuracy and best practices.",
        examples: "Let me explain the technical architecture...\nHere's how we can optimize this code...\nConsider these performance implications...",
        systemPrompt: "You are an experienced software engineer and technical consultant with extensive knowledge across multiple programming languages and software architectures. Your responses should be technically accurate, well-structured, and focused on best practices. Explain complex concepts clearly while maintaining technical precision. Prioritize scalability, maintainability, and performance in your recommendations."
      },
      {
        name: "Business Strategist",
        role: "Management consultant and business advisor",
        description: "A strategic thinker who helps businesses optimize operations and achieve growth objectives.",
        traits: "Strategic, Analytical, Results-driven, Collaborative",
        voice: "Professional and authoritative tone, focusing on actionable insights and measurable outcomes.",
        examples: "Based on market analysis...\nLet's examine the ROI of this initiative...\nHere's how we can optimize your business processes...",
        systemPrompt: "You are a seasoned business strategist with expertise in management consulting and business optimization. Your role is to provide strategic insights, analyze business challenges, and recommend practical solutions. Focus on data-driven decision making, market analysis, and actionable recommendations that drive business growth and operational efficiency."
      },
      {
        name: "Creative Director",
        role: "Design leader and creative professional",
        description: "A visionary designer who guides creative projects with an emphasis on innovation and brand consistency.",
        traits: "Innovative, Visionary, Detail-oriented, Collaborative",
        voice: "Inspiring and articulate, balancing creative vision with practical execution.",
        examples: "Let's explore the visual narrative...\nHere's how we can enhance the user experience...\nThis design approach aligns with your brand identity...",
        systemPrompt: "You are a creative director with extensive experience in design leadership and brand development. Your role is to guide creative decisions, maintain brand consistency, and push for innovative solutions. Balance artistic vision with practical constraints, and provide clear direction for design implementation. Focus on user experience, visual storytelling, and brand alignment in your recommendations."
      }
    ],
    "Educational": [
      {
        name: "Academic Mentor",
        role: "University professor and researcher",
        description: "A knowledgeable educator who specializes in making complex topics accessible while maintaining academic rigor.",
        traits: "Scholarly, Patient, Analytical, Thorough",
        voice: "Clear and educational, balancing academic precision with accessible explanations.",
        examples: "Let's break this concept down...\nConsider this theoretical framework...\nHere's how we can approach this research question...",
        systemPrompt: "You are an experienced academic mentor with a background in university teaching and research. Your role is to explain complex concepts clearly while maintaining academic rigor. Use examples and analogies to make difficult ideas accessible, but never oversimplify. Guide students through analytical thinking and research methodology. Encourage critical thinking and provide constructive feedback."
      },
      {
        name: "Learning Coach",
        role: "Educational consultant and learning specialist",
        description: "A supportive guide who helps learners develop effective study strategies and achieve educational goals.",
        traits: "Supportive, Adaptable, Encouraging, Practical",
        voice: "Friendly and encouraging, focusing on practical learning strategies and personal growth.",
        examples: "Let's develop a study plan that works for you...\nHere's a technique you might find helpful...\nLet's break this goal into manageable steps...",
        systemPrompt: "You are a learning coach specializing in educational support and study skill development. Your role is to help learners identify effective learning strategies, overcome academic challenges, and develop strong study habits. Focus on practical, actionable advice tailored to individual learning styles. Maintain an encouraging tone while providing structured guidance and constructive feedback."
      }
    ],
    "Creative": [
      {
        name: "Storyteller",
        role: "Fiction writer and narrative consultant",
        description: "An imaginative storyteller with a talent for creating engaging narratives across different genres and formats.",
        traits: "Creative, Imaginative, Empathetic, Articulate",
        voice: "Engaging and descriptive, with a focus on narrative elements and emotional resonance.",
        examples: "Let's develop this character arc...\nHere's how we can build tension in this scene...\nConsider this narrative perspective...",
        systemPrompt: "You are an experienced storyteller and narrative consultant with expertise in fiction writing and story development. Your role is to help craft compelling narratives, develop rich characters, and create engaging plot structures. Focus on elements of good storytelling including pacing, character development, world-building, and emotional resonance. Provide specific, actionable feedback while maintaining enthusiasm for the creative process."
      },
      {
        name: "Content Creator",
        role: "Digital content strategist and creator",
        description: "A versatile content specialist who crafts engaging material optimized for various platforms and audiences.",
        traits: "Adaptable, Strategic, Creative, Audience-focused",
        voice: "Dynamic and engaging, adapting tone and style to match platform and audience needs.",
        examples: "Let's optimize this content for your target audience...\nHere's how we can repurpose this across platforms...\nThis strategy will enhance engagement...",
        systemPrompt: "You are a skilled content creator and strategist specializing in digital platforms and audience engagement. Your role is to help develop and optimize content that resonates with specific audiences across different channels. Focus on content strategy, platform optimization, and audience engagement. Consider SEO best practices, content formatting, and platform-specific requirements while maintaining brand voice and messaging consistency."
      }
    ],
    "Specialized": [
      {
        name: "Data Analyst",
        role: "Data scientist and analytics professional",
        description: "A detail-oriented analyst who transforms complex data into actionable insights and clear visualizations.",
        traits: "Analytical, Precise, Methodical, Communicative",
        voice: "Clear and analytical, focusing on data-driven insights and practical applications.",
        examples: "The data suggests the following trends...\nLet's visualize this information to better understand...\nBased on the statistical analysis...",
        systemPrompt: "You are an experienced data analyst with expertise in data science and analytics. Your role is to help interpret complex data sets, identify meaningful patterns, and communicate insights clearly. Focus on statistical accuracy, data visualization, and practical applications of findings. Maintain a balance between technical precision and clear communication, making complex analyses accessible to non-technical stakeholders."
      },
      {
        name: "Marketing Strategist",
        role: "Marketing consultant and brand specialist",
        description: "A marketing professional who develops targeted campaigns and messaging that resonates with specific audiences.",
        traits: "Strategic, Creative, Data-driven, Customer-focused",
        voice: "Professional and persuasive, balancing creativity with marketing best practices.",
        examples: "Let's analyze your target audience...\nHere's how we can optimize your campaign...\nThis messaging strategy will resonate with...",
        systemPrompt: "You are a marketing strategist with extensive experience in campaign development and brand messaging. Your role is to help develop effective marketing strategies that align with business objectives and resonate with target audiences. Focus on market analysis, audience targeting, campaign optimization, and measurable outcomes. Combine creative thinking with data-driven decision making to deliver practical, results-oriented marketing solutions."
      }
    ]
  };
};

// server/auth.ts
init_storage();
import passport from "passport";
import { Strategy as LocalStrategy } from "passport-local";
import { Strategy as GoogleStrategy } from "passport-google-oauth20";
import session2 from "express-session";
import bcrypt from "bcrypt";
import { z } from "zod";

// server/session-mem-store.ts
import session from "express-session";
var MemorySessionStore = class extends session.Store {
  constructor() {
    super();
    this.sessions = /* @__PURE__ */ new Map();
    console.log("Memory session store initialized as a fallback");
    setInterval(() => {
      this.cleanup();
    }, 15 * 60 * 1e3);
  }
  cleanup() {
    const now = /* @__PURE__ */ new Date();
    let count = 0;
    for (const [sid, session3] of this.sessions.entries()) {
      if (session3.expires < now) {
        this.sessions.delete(sid);
        count++;
      }
    }
    if (count > 0) {
      console.log(`Cleaned up ${count} expired sessions`);
    }
  }
  get(sid, callback) {
    try {
      const sessionData = this.sessions.get(sid);
      if (!sessionData) {
        return callback(null, null);
      }
      if (sessionData.expires < /* @__PURE__ */ new Date()) {
        this.sessions.delete(sid);
        return callback(null, null);
      }
      return callback(null, sessionData.data);
    } catch (error) {
      return callback(error);
    }
  }
  set(sid, session3, callback) {
    try {
      const expiryMs = session3.cookie.originalMaxAge || 864e5;
      const expires = new Date(Date.now() + expiryMs);
      this.sessions.set(sid, {
        data: session3,
        expires
      });
      if (callback) callback();
    } catch (error) {
      if (callback) callback(error);
    }
  }
  destroy(sid, callback) {
    try {
      this.sessions.delete(sid);
      if (callback) callback();
    } catch (error) {
      if (callback) callback(error);
    }
  }
  touch(sid, session3, callback) {
    try {
      const sessionData = this.sessions.get(sid);
      if (sessionData) {
        const expiryMs = session3.cookie.originalMaxAge || 864e5;
        sessionData.expires = new Date(Date.now() + expiryMs);
        sessionData.data = session3;
        this.sessions.set(sid, sessionData);
      }
      if (callback) callback();
    } catch (error) {
      if (callback) callback(error);
    }
  }
  all(callback) {
    try {
      const now = /* @__PURE__ */ new Date();
      const result = Array.from(this.sessions.entries()).filter(([, session3]) => session3.expires > now).map(([sid, session3]) => ({ sid, session: session3.data }));
      callback(null, result);
    } catch (error) {
      callback(error);
    }
  }
  length(callback) {
    try {
      const now = /* @__PURE__ */ new Date();
      const count = Array.from(this.sessions.values()).filter((session3) => session3.expires > now).length;
      callback(null, count);
    } catch (error) {
      callback(error);
    }
  }
  clear(callback) {
    try {
      this.sessions.clear();
      if (callback) callback();
    } catch (error) {
      if (callback) callback(error);
    }
  }
};

// server/auth.ts
import cookieParser from "cookie-parser";
async function hashPassword(password) {
  const salt = await bcrypt.genSalt(10);
  return await bcrypt.hash(password, salt);
}
async function comparePasswords(password, hashedPassword) {
  return await bcrypt.compare(password, hashedPassword);
}
var loginSchema = z.object({
  email: z.string().email("Invalid email address"),
  password: z.string().min(6, "Password must be at least 6 characters")
});
var registerSchema = z.object({
  email: z.string().email("Invalid email address"),
  password: z.string().min(6, "Password must be at least 6 characters")
});
function setupAuth(app2) {
  const generateRandomSecret = () => {
    const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    let result = "";
    const length = 32;
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  };
  const SECRET_KEY = process.env.SESSION_SECRET || generateRandomSecret();
  const sessionStore = new MemorySessionStore();
  const sessionConfig = {
    name: "enhance.sid",
    // Custom cookie name
    secret: SECRET_KEY,
    resave: false,
    // Don't save session if unmodified
    saveUninitialized: false,
    // Don't create session until something stored
    store: sessionStore,
    cookie: {
      maxAge: 1e3 * 60 * 60 * 24 * 7,
      // 1 week
      httpOnly: true,
      // Helps with XSS attacks
      secure: process.env.NODE_ENV === "production",
      // Requires HTTPS in production
      sameSite: process.env.NODE_ENV === "production" ? "none" : "lax"
    }
  };
  app2.set("trust proxy", 1);
  app2.use(cookieParser(SECRET_KEY));
  const sessionMiddleware = session2(sessionConfig);
  app2.use((req, res, next) => {
    sessionMiddleware(req, res, (err) => {
      if (err) {
        console.error("Session middleware error:", err);
        req.sessionError = err;
        if (req.cookies && req.cookies.connect_sid) {
          res.clearCookie("connect.sid");
        }
        return next();
      }
      next();
    });
  });
  app2.use(passport.initialize());
  app2.use(passport.session());
  console.log(
    "Google OAuth credentials check:",
    process.env.GOOGLE_CLIENT_ID ? "GOOGLE_CLIENT_ID exists" : "GOOGLE_CLIENT_ID missing",
    process.env.GOOGLE_CLIENT_SECRET ? "GOOGLE_CLIENT_SECRET exists" : "GOOGLE_CLIENT_SECRET missing"
  );
  if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) {
    const callbackURL = "https://enhancemyprompt.com/api/auth/google/callback";
    console.log("Setting Google callback URL to:", callbackURL);
    passport.use(new GoogleStrategy({
      clientID: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      callbackURL,
      passReqToCallback: true
    }, async (req, accessToken, refreshToken, profile, done) => {
      try {
        console.log("GoogleStrategy verify callback invoked");
        console.log("Profile:", JSON.stringify(profile, null, 2));
        console.log("AccessToken:", accessToken);
        console.log("RefreshToken:", refreshToken);
        let user = await storage.getUserByGoogleId(profile.id);
        console.log("User from getUserByGoogleId:", user);
        if (user) {
          console.log("Returning existing user");
          return done(null, user);
        }
        const googleEmail = profile.emails && profile.emails[0] ? profile.emails[0].value : null;
        if (googleEmail) {
          user = await storage.getUserByEmail(googleEmail);
          console.log("User from getUserByEmail:", user);
          if (user) {
            user = await storage.updateUser(user.id, {
              // For now, we're not adding these fields to the user schema
              // We'll update the user schema later to add these fields
            });
            console.log("Updated user to link Google:", user);
            return done(null, user);
          }
        }
        if (googleEmail) {
          const username = profile.displayName ? profile.displayName.replace(/\s+/g, "").toLowerCase() : googleEmail.split("@")[0];
          const newUser = await storage.createUser({
            username,
            email: googleEmail
            // For now, we're not adding these fields to the user table
            // We'll update the schema later
          });
          console.log("Created new user:", newUser);
          return done(null, newUser);
        }
        console.error("No email found in Google profile");
        return done(new Error("No email found in Google profile"));
      } catch (error) {
        console.error("Google strategy error:", error);
        return done(error);
      }
    }));
  }
  passport.use(new LocalStrategy(
    { usernameField: "email" },
    // Configure to use email field instead of username
    async (email, password, done) => {
      try {
        const user = await storage.getUserByEmail(email);
        if (!user) {
          return done(null, false, { message: "Incorrect email or password" });
        }
        if (user.password) {
          const isMatch = await comparePasswords(password, user.password);
          if (!isMatch) {
            return done(null, false, { message: "Incorrect email or password" });
          }
        }
        return done(null, user);
      } catch (error) {
        return done(error);
      }
    }
  ));
  passport.serializeUser((user, done) => {
    done(null, user.id);
  });
  passport.deserializeUser(async (id, done) => {
    try {
      const user = await storage.getUser(id);
      if (!user) {
        return done(new Error("User not found"));
      }
      const { password, ...safeUser } = user;
      done(null, safeUser);
    } catch (error) {
      done(error);
    }
  });
  app2.post("/api/auth/register", async (req, res) => {
    try {
      const validatedData = registerSchema.parse(req.body);
      const existingUser = await storage.getUserByEmail(validatedData.email);
      if (existingUser) {
        return res.status(400).json({ error: "Email already exists" });
      }
      const hashedPassword = await hashPassword(validatedData.password);
      const newUser = await storage.createUser({
        username: validatedData.email.split("@")[0],
        // Use part of email as username
        email: validatedData.email,
        password: hashedPassword
      });
      const { password, ...userWithoutPassword } = newUser;
      req.login(newUser, (err) => {
        if (err) {
          return res.status(500).json({ error: "Error logging in after registration" });
        }
        return res.status(201).json(userWithoutPassword);
      });
    } catch (error) {
      if (error instanceof z.ZodError) {
        return res.status(400).json({ error: error.errors });
      }
      console.error("Registration error:", error);
      return res.status(500).json({ error: "Registration failed" });
    }
  });
  app2.post("/api/auth/login", (req, res, next) => {
    try {
      console.log("Login request received:", {
        body: req.body,
        headers: {
          origin: req.headers.origin,
          referer: req.headers.referer,
          host: req.headers.host,
          "user-agent": req.headers["user-agent"],
          "content-type": req.headers["content-type"],
          cookie: req.headers.cookie ? "Present (hidden for security)" : "Not present"
        },
        ip: req.ip,
        cookies: req.cookies || {},
        session: req.session ? { id: req.sessionID, cookie: req.session.cookie } : null
      });
      loginSchema.parse(req.body);
      passport.authenticate("local", (err, user, info) => {
        if (err) {
          console.error("Passport authenticate error:", err);
          return next(err);
        }
        if (!user) {
          console.log("Authentication failed:", info);
          return res.status(401).json({ error: info.message || "Authentication failed" });
        }
        req.login(user, (loginErr) => {
          if (loginErr) {
            console.error("Login error:", loginErr);
            return next(loginErr);
          }
          const { password, ...userWithoutPassword } = user;
          console.log("User logged in successfully:", {
            user: userWithoutPassword,
            sessionID: req.sessionID,
            cookie: req.session?.cookie
          });
          res.cookie("session_info", JSON.stringify({ loggedIn: true, timestamp: (/* @__PURE__ */ new Date()).toISOString() }), {
            maxAge: 1e3 * 60 * 60 * 24,
            // 1 day
            httpOnly: true,
            secure: true,
            sameSite: "none",
            path: "/"
          });
          return res.json(userWithoutPassword);
        });
      })(req, res, next);
    } catch (error) {
      console.error("Login route error:", error);
      if (error instanceof z.ZodError) {
        return res.status(400).json({ error: error.errors });
      }
      return res.status(500).json({ error: "Login failed: " + (error instanceof Error ? error.message : "Unknown error") });
    }
  });
  app2.post("/api/auth/logout", (req, res) => {
    req.logout((err) => {
      if (err) {
        return res.status(500).json({ error: "Logout failed" });
      }
      res.status(200).json({ message: "Logged out successfully" });
    });
  });
  app2.get("/api/auth/user", (req, res) => {
    console.log("GET /api/auth/user request from:", {
      origin: req.headers.origin,
      referer: req.headers.referer,
      host: req.headers.host,
      "user-agent": req.headers["user-agent"],
      cookie: req.headers.cookie ? "Present (hidden for security)" : "Not present",
      ip: req.ip,
      sessionID: req.sessionID,
      sessionExists: !!req.session,
      isAuthenticated: req.isAuthenticated()
    });
    if (!req.isAuthenticated()) {
      console.log("User authentication check failed - no session user found");
      return res.status(401).json({ error: "Not authenticated" });
    }
    console.log("User authenticated successfully:", {
      userID: req.user.id,
      username: req.user.username,
      email: req.user.email
    });
    res.json(req.user);
  });
  app2.get("/api/auth/diagnostics", (req, res) => {
    const diagnosticInfo = {
      sessionID: req.sessionID,
      cookies: req.cookies,
      headers: {
        origin: req.headers.origin,
        referer: req.headers.referer,
        host: req.headers.host,
        userAgent: req.headers["user-agent"]
      },
      isAuthenticated: req.isAuthenticated(),
      user: req.isAuthenticated() ? req.user : null,
      sessionError: req.sessionError ? {
        message: req.sessionError.message,
        name: req.sessionError.name,
        stack: req.sessionError.stack
      } : null
    };
    console.log("Diagnostic info:", JSON.stringify(diagnosticInfo, null, 2));
    res.json(diagnosticInfo);
  });
  if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) {
    console.log("Setting up Google OAuth routes with valid credentials");
    app2.get(
      "/api/auth/google",
      passport.authenticate("google", {
        scope: ["profile", "email"],
        prompt: "select_account"
        // Always prompt user to select account
      })
    );
    app2.get(
      "/api/auth/google/callback",
      passport.authenticate("google", {
        failureRedirect: "/auth?error=google-auth-failed"
      }),
      (req, res) => {
        console.log("Google callback route hit");
        console.log("req.user:", req.user);
        console.log("req.session:", req.session);
        const redirectTo = req.session?.returnTo || "/";
        delete req.session?.returnTo;
        console.log("Google authentication successful, redirecting to:", redirectTo);
        res.redirect(redirectTo);
      }
    );
    app2.get("/api/auth/google-login", (req, res) => {
      if (req.query.returnTo) {
        req.session.returnTo = req.query.returnTo;
      }
      res.redirect("/api/auth/google");
    });
  } else {
    console.log("Google OAuth credentials missing, setting up fallback routes");
    app2.get("/api/auth/google", (req, res) => {
      res.status(503).json({
        error: "Google authentication is not configured",
        message: "The server administrator needs to set up Google OAuth credentials"
      });
    });
    app2.get("/api/auth/google/callback", (req, res) => {
      res.redirect("/auth?error=google-auth-not-configured");
    });
    app2.get("/api/auth/google-login", (req, res) => {
      res.redirect("/auth?error=google-auth-not-configured");
    });
  }
  app2.use("/api/user/*", (req, res, next) => {
    console.log("Protected route accessed:", {
      path: req.path,
      method: req.method,
      sessionID: req.sessionID,
      hasSession: !!req.session,
      isAuthenticated: req.isAuthenticated(),
      user: req.user ? {
        id: req.user.id,
        email: req.user.email,
        subscriptionStatus: req.user.subscriptionStatus,
        subscriptionTier: req.user.subscriptionTier
      } : null,
      cookies: req.headers.cookie ? "Present" : "Missing"
    });
    if (!req.session) {
      console.error("No session found");
      return res.status(401).json({
        error: "No session found",
        code: "NO_SESSION"
      });
    }
    if (req.session.cookie.expires && /* @__PURE__ */ new Date() > req.session.cookie.expires) {
      console.error("Session expired");
      return res.status(401).json({
        error: "Session expired",
        code: "SESSION_EXPIRED"
      });
    }
    if (!req.isAuthenticated()) {
      console.error("User not authenticated");
      return res.status(401).json({
        error: "Authentication required",
        code: "AUTH_REQUIRED"
      });
    }
    if (!req.user) {
      console.error("No user object in authenticated session");
      return res.status(401).json({
        error: "User session invalid",
        code: "INVALID_USER"
      });
    }
    next();
  });
}

// server/init-personas.ts
async function initializeDefaultPersonas(storage2) {
  const templates2 = getPersonaTemplates();
  const defaultPersonas = Object.values(templates2).flat().map((template) => ({
    name: template.name || "",
    description: template.description || "",
    role: template.role || "",
    // Add reasonable defaults for required fields
    traits: template.traits || "Professional, Knowledgeable, Reliable",
    voice: template.voice || "Clear and professional communication style",
    examples: template.examples || "Example 1\nExample 2\nExample 3",
    systemPrompt: template.systemPrompt || `You are a ${template.role}. Respond in a professional and knowledgeable manner.`,
    isPublic: 1,
    // Make default templates public
    userId: null
    // No specific user owns these
  }));
  await storage2.initializePersonas(defaultPersonas);
  console.log(`Initialized ${defaultPersonas.length} default personas`);
}

// server/routes.ts
import express from "express";

// server/services/subscription/subscription-controller.ts
init_db();
init_schema();
import Stripe from "stripe";
import { eq as eq3 } from "drizzle-orm";

// server/services/usage-tracking.ts
init_db();
init_schema();
import { eq as eq2, sql } from "drizzle-orm";
var UsageTrackingService = class {
  static {
    this.retryAttempts = 3;
  }
  static {
    this.retryDelay = 500;
  }
  // milliseconds
  /**
   * Tracks a prompt enhancement usage for a user
   * Uses atomic updates and retries to ensure reliability
   */
  static async trackPromptEnhancement(userId, skipLimitCheck = false) {
    const FREE_TIER_LIMIT2 = 5;
    let attempt = 0;
    while (attempt < this.retryAttempts) {
      try {
        let [userUsageRecord] = await db.select().from(userUsage).where(eq2(userUsage.userId, userId));
        if (!userUsageRecord) {
          const [newRecord] = await db.insert(userUsage).values({
            userId,
            promptsUsed: 1,
            promptsLimit: 5,
            lastResetDate: /* @__PURE__ */ new Date(),
            nextResetDate: /* @__PURE__ */ new Date(),
            createdAt: /* @__PURE__ */ new Date(),
            updatedAt: /* @__PURE__ */ new Date(),
            enhancedPromptsCount: 0,
            generatedPersonasCount: 0
          }).returning();
          return {
            success: true,
            limitReached: false,
            currentUsage: 1,
            maxUsage: FREE_TIER_LIMIT2
          };
        }
        if (!skipLimitCheck && userUsageRecord.promptsUsed >= FREE_TIER_LIMIT2) {
          return {
            success: false,
            limitReached: true,
            currentUsage: userUsageRecord.promptsUsed,
            maxUsage: FREE_TIER_LIMIT2
          };
        }
        await db.update(userUsage).set({
          promptsUsed: userUsageRecord.promptsUsed + 1,
          updatedAt: /* @__PURE__ */ new Date()
        }).where(eq2(userUsage.id, userUsageRecord.id));
        return {
          success: true,
          limitReached: false,
          currentUsage: userUsageRecord.promptsUsed + 1,
          maxUsage: FREE_TIER_LIMIT2
        };
      } catch (error) {
        attempt++;
        if (attempt >= this.retryAttempts) throw error;
      }
    }
    return {
      success: false,
      limitReached: false,
      currentUsage: 0,
      maxUsage: FREE_TIER_LIMIT2
    };
  }
  /**
   * Check if a user has an active premium subscription
   */
  static async checkUserIsPremium(userId) {
    try {
      const [userRecord] = await db.select().from(userUsage).where(eq2(userUsage.userId, userId));
      return false;
    } catch (error) {
      console.error("Error checking premium status:", error);
      return false;
    }
  }
  /**
   * Gets the current usage statistics for a user
   */
  static async getUserUsage(userId) {
    try {
      let [userUsageRecord] = await db.select().from(userUsage).where(eq2(userUsage.userId, userId));
      console.log("userUsageRecord:", userUsageRecord);
      if (!userUsageRecord) {
        const [newRecord] = await db.insert(userUsage).values({
          userId,
          promptsUsed: 1,
          promptsLimit: 5,
          lastResetDate: /* @__PURE__ */ new Date(),
          nextResetDate: /* @__PURE__ */ new Date(),
          createdAt: /* @__PURE__ */ new Date(),
          updatedAt: /* @__PURE__ */ new Date(),
          enhancedPromptsCount: 0,
          generatedPersonasCount: 0
        }).returning();
        userUsageRecord = newRecord;
      }
      const usageHistory = await db.select({
        count: sql`count(*)`,
        month: sql`date_trunc('month', ${usageLogs.timestamp})`.as("month"),
        action: usageLogs.action
      }).from(usageLogs).where(eq2(usageLogs.userId, userId)).groupBy(sql`date_trunc('month', ${usageLogs.timestamp})`, usageLogs.action).orderBy(sql`date_trunc('month', ${usageLogs.timestamp}) DESC`).limit(3 * 2);
      const isPremium = false;
      const limit = isPremium ? Infinity : 5;
      const used = userUsageRecord.promptsUsed || 0;
      const remaining = isPremium ? Infinity : Math.max(0, 5 - used);
      const now = /* @__PURE__ */ new Date();
      const nextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1);
      const nextResetDate = nextMonth.toISOString();
      return {
        used,
        limit,
        remaining,
        nextResetDate,
        isUnlimited: isPremium
      };
    } catch (error) {
      console.error("Error getting user usage:", error);
      const now = /* @__PURE__ */ new Date();
      const nextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1);
      const nextResetDate = nextMonth.toISOString();
      return {
        used: 0,
        limit: 5,
        remaining: 5,
        nextResetDate,
        isUnlimited: false
      };
    }
  }
  /**
   * Reset monthly usage counters for testing
   */
  static async resetUserUsage(userId) {
    try {
      const currentDate = /* @__PURE__ */ new Date();
      const currentMonthStr = `${currentDate.getFullYear()}-${(currentDate.getMonth() + 1).toString().padStart(2, "0")}-01`;
      await db.update(userUsage).set({
        generatedPersonasCount: 0,
        updatedAt: /* @__PURE__ */ new Date()
      }).where(eq2(userUsage.userId, userId));
      await db.insert(usageLogs).values({
        userId,
        action: "reset_counters",
        timestamp: /* @__PURE__ */ new Date()
      });
      return true;
    } catch (error) {
      console.error("Error resetting user usage:", error);
      return false;
    }
  }
};

// server/services/subscription/subscription-controller.ts
if (!process.env.STRIPE_SECRET_KEY) {
  console.warn("Missing Stripe Secret Key - payment functionality will be unavailable");
}
var stripe = process.env.STRIPE_SECRET_KEY ? new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: "2023-10-16" }) : null;
var SubscriptionController = class _SubscriptionController {
  /**
   * Get subscription status for the current user
   */
  static async getSubscriptionStatus(req, res) {
    try {
      if (!req.isAuthenticated() || !req.user) {
        res.status(401).json({ error: "Not authenticated" });
        return;
      }
      const userId = req.user.id;
      const [user] = await db.select().from(users).where(eq3(users.id, userId));
      if (!user) {
        res.status(404).json({ error: "User not found" });
        return;
      }
      const userUsageData = await UsageTrackingService.getUserUsage(userId);
      let subscription = null;
      let expiresAt = null;
      if (user.stripeSubscriptionId && stripe) {
        try {
          subscription = await stripe.subscriptions.retrieve(user.stripeSubscriptionId);
          if (subscription.current_period_end) {
            expiresAt = new Date(subscription.current_period_end * 1e3).toISOString();
          }
        } catch (stripeError) {
          console.error("Error fetching Stripe subscription:", stripeError);
        }
      }
      const subscriptionData = {
        tier: userUsageData.subscriptionTier || "free",
        status: userUsageData.subscriptionStatus || "inactive",
        stripeCustomerId: user.stripeCustomerId || null,
        stripeSubscriptionId: user.stripeSubscriptionId || null,
        expiresAt
      };
      res.status(200).json(subscriptionData);
    } catch (error) {
      console.error("Error getting subscription status:", error);
      res.status(500).json({ error: "Failed to get subscription status" });
    }
  }
  /**
   * Create a checkout session for subscription signup or management
   */
  static async createCheckoutSession(req, res) {
    try {
      if (!stripe) {
        res.status(500).json({ error: "Stripe is not configured" });
        return;
      }
      if (!req.isAuthenticated() || !req.user) {
        res.status(401).json({ error: "Not authenticated" });
        return;
      }
      const userId = req.user.id;
      const [user] = await db.select().from(users).where(eq3(users.id, userId));
      if (!user) {
        res.status(404).json({ error: "User not found" });
        return;
      }
      let customerId = user.stripeCustomerId;
      if (!customerId) {
        const customer = await stripe.customers.create({
          email: user.email,
          name: user.username,
          metadata: {
            userId: userId.toString()
          }
        });
        customerId = customer.id;
        await db.update(users).set({ stripeCustomerId: customerId }).where(eq3(users.id, userId));
      }
      const mode = user.stripeSubscriptionId ? "customer_portal" : "subscription";
      if (mode === "customer_portal") {
        const session3 = await stripe.billingPortal.sessions.create({
          customer: customerId,
          return_url: `${req.protocol}://${req.get("host")}/account`
        });
        res.status(200).json({ url: session3.url });
      } else {
        const priceId = process.env.STRIPE_PRICE_ID || "price_1NeJVmGbvmrBM1PgSJGOUYZR";
        const session3 = await stripe.checkout.sessions.create({
          customer: customerId,
          payment_method_types: ["card"],
          line_items: [
            {
              price: priceId,
              quantity: 1
            }
          ],
          mode: "subscription",
          success_url: `${req.protocol}://${req.get("host")}/account?success=true`,
          cancel_url: `${req.protocol}://${req.get("host")}/account?canceled=true`,
          metadata: {
            userId: userId.toString()
          }
        });
        res.status(200).json({ url: session3.url });
      }
    } catch (error) {
      console.error("Error creating checkout session:", error);
      res.status(500).json({ error: "Failed to create checkout session" });
    }
  }
  /**
   * Handle Stripe webhook events related to subscriptions
   */
  static async handleWebhook(req, res) {
    if (!stripe) {
      res.status(500).json({ error: "Stripe is not configured" });
      return;
    }
    const sig = req.headers["stripe-signature"];
    const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;
    if (!endpointSecret) {
      console.error("Missing Stripe webhook secret");
      res.status(500).json({ error: "Webhook secret not configured" });
      return;
    }
    let event;
    try {
      event = stripe.webhooks.constructEvent(
        req.rawBody,
        sig,
        endpointSecret
      );
    } catch (err) {
      console.error(`Webhook Error: ${err.message}`);
      res.status(400).send(`Webhook Error: ${err.message}`);
      return;
    }
    try {
      switch (event.type) {
        case "checkout.session.completed": {
          const session3 = event.data.object;
          await _SubscriptionController.handleCheckoutSessionCompleted(session3);
          break;
        }
        case "customer.subscription.updated": {
          const subscription = event.data.object;
          await _SubscriptionController.handleSubscriptionUpdated(subscription);
          break;
        }
        case "customer.subscription.deleted": {
          const subscription = event.data.object;
          await _SubscriptionController.handleSubscriptionDeleted(subscription);
          break;
        }
        default:
          console.log(`Unhandled event type: ${event.type}`);
      }
      res.status(200).json({ received: true });
    } catch (error) {
      console.error("Error handling webhook:", error);
      res.status(500).json({ error: "Failed to process webhook" });
    }
  }
  /**
   * Handle checkout session completed event
   */
  static async handleCheckoutSessionCompleted(session3) {
    if (!stripe) return;
    if (!session3.metadata?.userId) {
      console.error("Missing userId in session metadata");
      return;
    }
    const userId = parseInt(session3.metadata.userId);
    if (session3.mode !== "subscription" || !session3.subscription) {
      console.log("Not a subscription checkout");
      return;
    }
    const subscription = await stripe.subscriptions.retrieve(
      session3.subscription
    );
    await db.update(users).set({
      stripeSubscriptionId: subscription.id,
      subscriptionStatus: subscription.status,
      subscriptionTier: "premium",
      subscriptionExpiresAt: new Date(subscription.current_period_end * 1e3)
    }).where(eq3(users.id, userId));
    const currentDate = /* @__PURE__ */ new Date();
    const currentMonthStr = `${currentDate.getFullYear()}-${(currentDate.getMonth() + 1).toString().padStart(2, "0")}-01`;
    const [userUsageRecord] = await db.select().from(userUsage).where(
      eq3(userUsage.userId, userId)
    );
    if (userUsageRecord) {
      await db.update(userUsage).set({
        subscriptionTier: "premium",
        subscriptionStatus: subscription.status,
        updatedAt: /* @__PURE__ */ new Date()
      }).where(eq3(userUsage.id, userUsageRecord.id));
    } else {
      await db.insert(userUsage).values({
        userId,
        enhancedPromptsCount: 0,
        generatedPersonasCount: 0,
        subscriptionTier: "premium",
        subscriptionStatus: subscription.status
      });
    }
  }
  /**
   * Handle subscription updated event
   */
  static async handleSubscriptionUpdated(subscription) {
    if (!stripe) return;
    const [user] = await db.select().from(users).where(eq3(users.stripeSubscriptionId, subscription.id));
    if (!user) {
      console.error(`No user found with subscription ID: ${subscription.id}`);
      return;
    }
    await db.update(users).set({
      subscriptionStatus: subscription.status,
      subscriptionTier: subscription.status === "active" ? "premium" : "free",
      subscriptionExpiresAt: new Date(subscription.current_period_end * 1e3)
    }).where(eq3(users.id, user.id));
    const currentDate = /* @__PURE__ */ new Date();
    const currentMonthStr = `${currentDate.getFullYear()}-${(currentDate.getMonth() + 1).toString().padStart(2, "0")}-01`;
    const [userUsageRecord] = await db.select().from(userUsage).where(
      eq3(userUsage.userId, user.id)
    );
    if (userUsageRecord) {
      await db.update(userUsage).set({
        subscriptionTier: subscription.status === "active" ? "premium" : "free",
        subscriptionStatus: subscription.status,
        updatedAt: /* @__PURE__ */ new Date()
      }).where(eq3(userUsage.id, userUsageRecord.id));
    }
  }
  /**
   * Handle subscription deleted event
   */
  static async handleSubscriptionDeleted(subscription) {
    if (!stripe) return;
    const [user] = await db.select().from(users).where(eq3(users.stripeSubscriptionId, subscription.id));
    if (!user) {
      console.error(`No user found with subscription ID: ${subscription.id}`);
      return;
    }
    await db.update(users).set({
      subscriptionStatus: "canceled",
      subscriptionTier: "free"
    }).where(eq3(users.id, user.id));
    const [userUsageRecord] = await db.select().from(userUsage).where(
      eq3(userUsage.userId, user.id)
    );
    if (userUsageRecord) {
      await db.update(userUsage).set({
        subscriptionTier: "free",
        subscriptionStatus: "canceled",
        updatedAt: /* @__PURE__ */ new Date()
      }).where(eq3(userUsage.id, userUsageRecord.id));
    }
  }
};

// server/routes.ts
if (!process.env.STRIPE_SECRET_KEY) {
  console.warn("Missing Stripe Secret Key - payment functionality will be unavailable");
}
var stripe2 = process.env.STRIPE_SECRET_KEY ? new Stripe2(process.env.STRIPE_SECRET_KEY, { apiVersion: "2023-10-16" }) : null;
async function registerRoutes(app2) {
  setupAuth(app2);
  app2.get("/api/subscription", SubscriptionController.getSubscriptionStatus);
  app2.post("/api/subscription/checkout", SubscriptionController.createCheckoutSession);
  app2.post("/api/webhook/stripe", express.raw({ type: "application/json" }), SubscriptionController.handleWebhook);
  app2.get("/api/user/usage", async (req, res) => {
    try {
      if (!req.isAuthenticated() || !req.user) {
        return res.status(401).json({ error: "Not authenticated" });
      }
      const userId = req.user.id;
      const usageData = await UsageTrackingService.getUserUsage(userId);
      res.status(200).json(usageData);
    } catch (error) {
      console.error("Error fetching user usage:", error);
      res.status(500).json({ error: "Failed to fetch usage data" });
    }
  });
  app2.post("/api/user/usage/reset", async (req, res) => {
    try {
      if (!req.isAuthenticated() || !req.user) {
        return res.status(401).json({ error: "Not authenticated" });
      }
      const userId = req.user.id;
      const success = await UsageTrackingService.resetUserUsage(userId);
      if (success) {
        res.status(200).json({ message: "Usage counters reset successfully" });
      } else {
        res.status(500).json({ error: "Failed to reset usage counters" });
      }
    } catch (error) {
      console.error("Error resetting usage counters:", error);
      res.status(500).json({ error: "Failed to reset usage counters" });
    }
  });
  try {
    await storage.initializePromptKnowledge([]);
    await storage.initializeTemplates([]);
    const existingPersonas = await storage.getPublicPersonas();
    if (!existingPersonas || existingPersonas.length === 0) {
      await initializeDefaultPersonas(storage);
    } else {
      console.log("Default personas already exist, skipping seed");
    }
    const { initializePromptEngineeringCourse: initializePromptEngineeringCourse2 } = await Promise.resolve().then(() => (init_init_learning_paths(), init_learning_paths_exports));
    await initializePromptEngineeringCourse2(storage);
    console.log("Database initialized with default templates, personas, knowledge, and learning paths");
  } catch (error) {
    console.error("Error initializing database:", error);
  }
  app2.get("/api/admin/update-fundamentals-course", async (req, res) => {
    try {
      const { eq: eq8 } = await import("drizzle-orm");
      const { learningPaths: learningPaths3, learningModules: learningModules3, learningLessons: learningLessons3, learningChallenges: learningChallenges3 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
      const pathId = 1;
      const [path3] = await db.select().from(learningPaths3).where(eq8(learningPaths3.id, pathId));
      if (!path3) {
        return res.json({ message: "Fundamentals learning path not found." });
      }
      console.log(`Updating the "${path3.title}" learning path (ID: ${pathId})`);
      const existingModules = await db.select().from(learningModules3).where(eq8(learningModules3.pathId, pathId));
      console.log(`Found ${existingModules.length} existing modules`);
      const moduleData = [
        {
          title: "Understanding LLM Capabilities & Limitations",
          description: "Learn how LLMs work, compare major LLM providers, and understand their capabilities and limitations for effective prompt engineering.",
          order: 1,
          requiredPoints: 0,
          estimatedHours: 2,
          bannerImage: "https://images.unsplash.com/photo-1617791160505-6f00504e3519?q=80&w=2940&auto=format&fit=crop"
        },
        {
          title: "Core Prompt Engineering Techniques",
          description: "Master the fundamentals of prompt construction, essential patterns, and principles of clarity and specificity.",
          order: 2,
          requiredPoints: 50,
          estimatedHours: 2,
          bannerImage: "https://images.unsplash.com/photo-1655720033654-a4239dd42d10?q=80&w=2940&auto=format&fit=crop"
        },
        {
          title: "Practical Applications & Use Cases",
          description: "Explore real-world applications including content generation, analysis and extraction, and decision support systems.",
          order: 3,
          requiredPoints: 100,
          estimatedHours: 2,
          bannerImage: "https://images.unsplash.com/photo-1688891982748-830800e5833f?q=80&w=2940&auto=format&fit=crop"
        },
        {
          title: "Testing & Iterative Improvement",
          description: "Learn structured testing approaches, understand common failure modes, and develop continuous improvement processes.",
          order: 4,
          requiredPoints: 150,
          estimatedHours: 2,
          bannerImage: "https://images.unsplash.com/photo-1638571447486-ed5a87abcc4f?q=80&w=3032&auto=format&fit=crop"
        }
      ];
      const updatedModules = [];
      for (let i = 0; i < moduleData.length; i++) {
        const moduleInfo = moduleData[i];
        const existingModule = existingModules.find((m) => m.order === moduleInfo.order);
        if (existingModule) {
          console.log(`Updating module "${moduleInfo.title}" (ID: ${existingModule.id})`);
          const [updatedModule] = await db.update(learningModules3).set({
            title: moduleInfo.title,
            description: moduleInfo.description,
            estimatedHours: moduleInfo.estimatedHours,
            bannerImage: moduleInfo.bannerImage,
            requiredPoints: moduleInfo.requiredPoints
          }).where(eq8(learningModules3.id, existingModule.id)).returning();
          updatedModules.push(updatedModule);
          await updateModuleLessons(existingModule.id, moduleInfo.order);
        } else {
          console.log(`Creating new module "${moduleInfo.title}"`);
          const [newModule] = await db.insert(learningModules3).values({
            pathId,
            title: moduleInfo.title,
            description: moduleInfo.description,
            order: moduleInfo.order,
            requiredPoints: moduleInfo.requiredPoints,
            estimatedHours: moduleInfo.estimatedHours,
            bannerImage: moduleInfo.bannerImage
          }).returning();
          updatedModules.push(newModule);
          await updateModuleLessons(newModule.id, moduleInfo.order);
        }
      }
      return res.json({
        message: "Successfully updated Prompt Engineering Fundamentals course",
        updatedModules: updatedModules.map((m) => m.title)
      });
    } catch (error) {
      console.error("Error updating fundamentals course:", error);
      res.status(500).json({ error: "Failed to update fundamentals course" });
    }
    async function updateModuleLessons(moduleId, moduleNumber) {
      const { eq: eq8 } = await import("drizzle-orm");
      const { learningLessons: learningLessons3, learningChallenges: learningChallenges3 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
      const existingLessons = await db.select().from(learningLessons3).where(eq8(learningLessons3.moduleId, moduleId));
      console.log(`Found ${existingLessons.length} existing lessons for module ID ${moduleId}`);
      let lessonData = [];
      if (moduleNumber === 1) {
        lessonData = [
          {
            title: "How LLMs Work: A Non-Technical Overview",
            description: "Understand how large language models process text as tokens, recognize patterns, and generate responses",
            content: `# How LLMs Work: A Non-Technical Overview

Large Language Models (LLMs) operate on straightforward principles that anyone can understand, even without a technical background:

## Key Concepts

- LLMs are pattern recognition systems trained on vast text datasets
- They predict the most likely next words based on the input they receive
- Think of them as sophisticated autocomplete systems with deep pattern recognition
- They don't "understand" or "think" in the human sense, but simulate understanding through pattern matching

## Token-Based Processing

LLMs process text as "tokens" (roughly parts of words). For example, "THE QUICK BROWN FOX" might be processed as ["THE", " QUICK", " BROWN", " FOX"].

Each model has a maximum number of tokens it can process at once, which has practical implications:
- Longer inputs require more tokens
- More detailed prompts provide better context but consume more tokens
- Always consider token efficiency in your prompting strategy

## Context Windows

The context window is a fundamental concept that determines what an LLM can "remember" during a conversation:
- It's the total "memory" available to the LLM
- Everything you ask must fit within this window, including your prompt and the model's response
- Context window sizes vary by model (8K tokens for some, 100K+ for others)

When a context window is full, the earliest parts of the conversation might be pushed out and "forgotten" by the model.`,
            type: "theory",
            order: 1,
            pointsReward: 20,
            estimatedMinutes: 15
          },
          {
            title: "Major LLM Players and Their Differences",
            description: "Compare the capabilities, strengths, and limitations of leading LLM providers",
            content: "# Major LLM Players and Their Differences\n\nThe LLM landscape includes several major providers, each with unique strengths and limitations. Understanding these differences will help you choose the right model for specific needs.\n\n## OpenAI (GPT Models)\n\n- **GPT-4o**: Latest flagship model with strong multimodal capabilities\n- **ChatGPT**: Consumer-facing interface with various subscription tiers\n- **Key Strengths**: General knowledge, coding, creative tasks\n- **Limitations**: May occasionally hallucinate, has knowledge cutoff dates\n\n## Anthropic (Claude Models)\n\n- Claude 3 family (Opus, Sonnet, Haiku)\n- **Key Strengths**: Longer context windows, nuanced reasoning, reduced hallucinations\n- **Limitations**: Sometimes more conservative in generating certain content\n\n## Google (Gemini Models)\n\n- Gemini Pro and Ultra versions\n- **Key Strengths**: Real-time information, multimodal capabilities\n- **Limitations**: Varying performance across specialized domains\n\n## Open-source Alternatives\n\n- Mistral, Llama, and other foundation models\n- **Key Strengths**: Customizability, privacy, self-hosting options\n- **Limitations**: Often require more technical expertise to implement effectively\n\nWhen working with different models, adjust your prompting strategy to leverage their specific strengths and work around their limitations.",
            type: "theory",
            order: 2,
            pointsReward: 25,
            estimatedMinutes: 20
          },
          {
            title: "Setting Appropriate Expectations",
            description: "Learn what LLMs can and cannot do to design more effective prompts and avoid common pitfalls",
            content: "# Setting Appropriate Expectations\n\nOne of the most important skills in working with LLMs is understanding their capabilities and limitations. Setting appropriate expectations helps you design more effective prompts and avoid common pitfalls.\n\n## What LLMs Can Do\n\n- Generate content (articles, emails, code, etc.)\n- Summarize information\n- Translate languages\n- Answer general knowledge questions (within their training data)\n- Follow complex instructions\n- Adapt to different tones and styles\n- Provide creative ideas and suggestions\n\n## What LLMs Cannot Do\n\n- Access real-time data (without tools)\n- Perform true reasoning (they simulate reasoning)\n- Guarantee factual accuracy\n- Access or modify files on your computer\n- Execute code (without additional systems)\n- Have personal experiences or emotions\n- Maintain perfect consistency across long outputs\n\n## Common Failure Modes\n\nUnderstanding how and why LLMs fail helps you anticipate and prevent issues:\n\n- **Hallucinations**: Confidently presenting incorrect information as fact\n- **Refusals**: Declining to complete requests due to safety protocols\n- **Misunderstandings**: Interpreting ambiguous prompts in unexpected ways\n- **Repetition**: Getting stuck in loops or producing redundant content\n\nBy setting realistic expectations about what LLMs can and cannot do, you'll be able to design more effective prompts and build more reliable AI-powered solutions.",
            type: "theory",
            order: 3,
            pointsReward: 20,
            estimatedMinutes: 15
          }
        ];
      } else if (moduleNumber === 2) {
        lessonData = [
          {
            title: "Prompt Anatomy & Construction",
            description: "Learn the components of well-structured prompts and how to build them systematically",
            content: '# Prompt Anatomy & Construction\n\nEffective prompts have a clear structure that helps the LLM understand exactly what you want. A well-constructed prompt typically includes several key components.\n\n## Context Setting and Framing\n\nThe first component of an effective prompt is proper context setting:\n- Establish clear boundaries and expectations\n- Define the scenario or environment\n- Provide relevant background information\n\n**Example**: "You are analyzing quarterly sales data for a retail company that operates in 5 regions..."\n\n## Task Definition vs. Input Data\n\nClearly separating your instructions from the data being processed improves results:\n- Task definition: The specific instruction or question\n- Input data: The information being processed\n- Clear separation improves model performance\n\n**Example Template**:\n```\nContext: [background information]\nTask: [specific instruction]\nInput: [data to be processed]\nExpected Output: [format or example of desired response]\n```\n\n## Output Format Specification\n\nBeing explicit about how you want information structured leads to more usable results:\n- Explicitly define how you want information structured\n- Use formatting examples for consistent results\n- Consider specifying:\n  - Length (short vs. comprehensive)\n  - Style (formal, conversational, technical)\n  - Organization (bullet points, numbered lists, paragraphs)\n  - Special formatting (tables, JSON, markdown)\n\nBy understanding and implementing these core components of prompt anatomy, you can craft prompts that consistently produce better results across different models and use cases.',
            type: "theory",
            order: 1,
            pointsReward: 25,
            estimatedMinutes: 20
          },
          {
            title: "Essential Prompt Patterns",
            description: "Master key prompt patterns that consistently produce better results across different LLMs",
            content: '# Essential Prompt Patterns\n\nCertain prompt patterns consistently produce better results across different LLMs and use cases. These patterns can be combined and adapted to suit your specific needs.\n\n## Role Assignment ("Act as a...")\n\nDirects the model to adopt a specific perspective or expertise:\n- "Act as a financial analyst examining these quarterly results..."\n- "Take on the role of a marketing strategist evaluating this campaign..."\n\n**Best practices**:\n- Be specific about the role\'s expertise level\n- Include relevant constraints or ethical guidelines\n- Pair with clear output expectations\n\n## Step-by-Step Instructions\n\nBreak complex tasks into sequential steps:\n- Reduces errors and omissions\n- Creates more structured outputs\n- Improves reasoning on complex tasks\n\n**Example**:\n```\nAnalyze this customer feedback by:\n1. Identifying the main themes mentioned\n2. Categorizing sentiment as positive, negative, or neutral\n3. Suggesting three actionable improvements based on the feedback\n4. Prioritizing these improvements by potential impact\n```\n\n## "Few-Shot" Examples for Consistent Formats\n\nProvide 2-3 examples of desired input/output pairs:\n- Particularly effective for specific formatting requirements\n- Useful for classification tasks\n- Helps maintain consistent tone or style\n\n## Constrained Generation Techniques\n\nSet specific limitations or requirements:\n- Word/character counts\n- Required inclusions/exclusions\n- Tone or reading level constraints\n\n**Example**:\n```\nCreate a company announcement about our new product launch.\nRequirements:\n- Maximum 100 words\n- Include our tagline "Innovation for Everyone"\n- Appropriate for all employees (technical and non-technical)\n- Avoid industry jargon\n```\n\nBy applying these essential prompt patterns, you\'ll be able to consistently get better results from any LLM.',
            type: "technique",
            order: 2,
            pointsReward: 30,
            estimatedMinutes: 25
          },
          {
            title: "Clarity & Specificity Principles",
            description: "Apply principles to create clear, specific prompts that minimize ambiguity and maximize results",
            content: `# Clarity & Specificity Principles

The clarity and specificity of your prompts directly impact the quality of LLM outputs. Applying these principles helps minimize ambiguity and maximize results.

## Avoiding Ambiguity

- Identify and eliminate vague terms
- Use precise language and specific metrics
- Define subjective terms when necessary

**Before**: "Make this email better"
**After**: "Revise this email to be more persuasive by emphasizing customer benefits and including a clear call to action"

## Providing Necessary Context

- Include relevant background information
- Define audience and purpose
- Establish constraints and limitations

**Example**: "This presentation will be delivered to senior executives who have limited technical knowledge but need to understand the business implications of our new technology."

## Setting Clear Evaluation Criteria

- Define what success looks like
- Provide clear priorities when objectives may conflict
- Establish boundaries for the response

**Example**: "Prioritize clarity over comprehensiveness. It's more important that the executives understand the three key benefits than to cover every technical detail."

## Using Precise Instructions and Parameters

- Specify exact requirements and constraints
- Use numbers and specific measurements
- Provide clear boundaries and limits

**Example**: "Create 3-5 social media posts (each under 280 characters) that highlight the sustainability features of our new product. Each post should include exactly one call to action and be appropriate for a LinkedIn audience."

These clarity and specificity principles are essential for consistently getting high-quality results from language models. By reducing ambiguity and being explicit about your requirements, you'll significantly improve the relevance and usefulness of LLM outputs.`,
            type: "principle",
            order: 3,
            pointsReward: 25,
            estimatedMinutes: 20
          }
        ];
      } else if (moduleNumber === 3) {
        lessonData = [
          {
            title: "Content Generation Applications",
            description: "Learn how to effectively use LLMs for various content generation tasks in professional settings",
            content: "# Content Generation Applications\n\nOne of the most common and valuable applications of LLMs is generating various types of content. This lesson explores how to effectively use LLMs for different content generation tasks.\n\n## Structured Writing (Emails, Reports, Summaries)\n\nLLMs excel at generating structured business communications when given proper guidance:\n- Templates for different document types\n- Formal business emails\n- Executive summaries\n- Project reports\n- Meeting minutes\n\n**Effective Email Generation Prompt Example**:\n```\nDraft a follow-up email to a potential client who attended our product demo yesterday.\nInclude:\n- A thank you for their time\n- A summary of their main questions/concerns\n- Clear next steps with timeline\n- Our unique value proposition that addresses their specific needs\nTone: Professional but warm\nLength: 150-200 words\n```\n\n## Creative Ideation and Brainstorming\n\nLLMs can be powerful brainstorming partners when prompted effectively:\n- Constraint-based creativity\n- Cross-industry inspiration\n- Perspective-shifting techniques\n\n**Perspective-Shifting Prompt Example**:\n```\nI'm trying to improve our customer onboarding process for our SaaS platform.\nHelp me see this process from multiple perspectives by:\n- First, describing the typical pain points from a new customer's perspective\n- Then, identifying efficiency concerns from our support team's perspective\n- Next, highlighting data collection opportunities from our marketing team's perspective\n- Finally, noting security considerations from our IT department's perspective\nFor each perspective, suggest 2-3 specific improvements that would address their primary concerns.\n```\n\n## Outlining and Content Planning\n\nLLMs can help create structured outlines for various content types:\n- Blog posts and articles\n- Presentation structures\n- Course materials\n- Product documentation\n\n**Blog Post Planning Prompt Example**:\n```\nHelp me plan a comprehensive blog post about \"The Future of Remote Work Technology\" with the following elements:\n- An attention-grabbing introduction that highlights the rapid evolution of remote work tools\n- A section on current technology limitations and pain points\n- 3-4 sections on emerging technologies that will transform remote collaboration (with specific examples)\n- A section on implementation challenges and adoption strategies\n- A forward-looking conclusion with actionable takeaways\nFor each section, provide:\n- A compelling subheading\n- 3-5 bullet points of key information to include\n- At least one suggestion for a relevant statistic, quote, or example to incorporate\nThe target audience is IT decision-makers at mid-sized companies.\n```\n\nBy applying these techniques, you can leverage LLMs to generate high-quality content efficiently across various business and professional needs.",
            type: "application",
            order: 1,
            pointsReward: 30,
            estimatedMinutes: 25
          },
          {
            title: "Analysis & Extraction Applications",
            description: "Discover techniques for leveraging LLMs to analyze data and extract valuable insights",
            content: "# Analysis & Extraction Applications\n\nLLMs excel at analyzing and extracting insights from text data. This lesson explores how to leverage LLMs for various analysis and extraction tasks.\n\n## Data Summarization and Insight Generation\n\nLLMs can help extract meaning from complex information:\n- Techniques for extracting meaning from complex information\n- Frameworks for identifying patterns and trends\n- Methods for prioritizing insights by relevance\n\n**Structured Insight Generation Example**:\n```\nAnalyze these quarterly sales figures using the following framework:\n1. Performance Summary:\n   - Overall performance vs. targets\n   - Year-over-year comparison\n   - Key metrics summary (revenue, units, profit margin)\n2. Pattern Identification:\n   - Top and bottom performing products/regions\n   - Emerging trends (growing/declining categories)\n   - Seasonal factors affecting performance\n3. Anomaly Detection:\n   - Unexpected results that warrant investigation\n   - Potential data issues or reporting anomalies\n4. Strategic Implications:\n   - 3-5 key insights that should inform strategy\n   - Potential opportunities based on the data\n   - Suggested areas for resource allocation\n```\n\n## Information Extraction from Unstructured Text\n\nLLMs can transform unstructured text into structured data:\n- Identifying specific data points from documents\n- Creating structured formats from narrative text\n- Extracting entities, relationships, and attributes\n\n**Entity Extraction Example**:\n```\nFrom the following press release, extract all mentioned:\n- Companies (including the issuing company and any partners/competitors)\n- Products or services\n- People (with their titles/roles)\n- Locations (cities, countries, regions)\n- Dates and timeframes\n- Financial figures (revenue, growth percentages, etc.)\nFor each entity, provide the category and the exact text where it appears in the document.\nFormat the output as a JSON object grouped by entity type.\n```\n\n## Comparative Analysis of Documents or Concepts\n\nLLMs can help compare and contrast information across sources:\n- Side-by-side evaluation frameworks\n- Identifying similarities and differences\n- Objective comparison across multiple dimensions\n\n**Multi-Dimensional Comparison Framework Example**:\n```\nCompare these three project management methodologies (Agile, Waterfall, and Kanban) across the following dimensions:\n- Core Philosophy & Principles\n- Planning & Requirements Handling\n- Team Structure & Roles\n- Progress Tracking & Reporting\n- Change Management Approach\n- Ideal Project Types\n- Common Challenges & Limitations\nFor each dimension, provide a brief description of how each methodology approaches it, highlighting key similarities and differences.\nConclude with a decision framework to help teams choose the right methodology based on project characteristics.\n```\n\nThese applications demonstrate how LLMs can be powerful tools for analyzing and extracting insights from various types of text data.",
            type: "application",
            order: 2,
            pointsReward: 30,
            estimatedMinutes: 25
          },
          {
            title: "Decision Support Applications",
            description: "Explore how to use LLMs to structure decision-making processes and provide balanced analysis",
            content: "# Decision Support Applications\n\nLLMs can be valuable tools for structuring decision-making processes. This lesson explores how to use LLMs for various decision support applications.\n\n## Pros/Cons Analysis\n\nLLMs can help evaluate options in a balanced way:\n- Balanced evaluation frameworks\n- Identifying non-obvious implications\n- Challenging assumptions and biases\n\n**Pros/Cons Analysis Example**:\n```\nEvaluate the decision to migrate our on-premises database to a cloud solution.\nFor each of these perspectives (technical, financial, operational, security, and strategic):\n1. Identify 3-4 specific pros of migration\n2. Identify 3-4 specific cons or risks\n3. For each con, suggest a potential mitigation strategy\nFormat as a structured table with clearly labeled sections for each perspective.\n```\n\n## Multi-Criteria Decision Frameworks\n\nLLMs can apply complex decision frameworks to specific scenarios:\n- SWOT analysis (Strengths, Weaknesses, Opportunities, Threats)\n- Decision matrices with weighted criteria\n- Scenario planning and analysis\n\n**Weighted Decision Matrix Example**:\n```\nHelp me evaluate three potential office locations using a weighted decision matrix.\nCriteria and weights:\n- Cost (30%): Monthly rent and operational expenses\n- Location (25%): Proximity to clients and transportation\n- Facilities (20%): Space, amenities, and technology infrastructure\n- Flexibility (15%): Lease terms and ability to expand/contract\n- Image (10%): Brand perception and professional appearance\nFor each criterion, rate the options on a scale of 1-5, multiply by the weight, and calculate a total score.\nPresent the results in a table format with a clear recommendation based on the highest weighted score.\n```\n\n## Risk Assessment and Mitigation Planning\n\nLLMs can help identify and address potential risks:\n- Systematic risk identification processes\n- Impact and probability assessments\n- Mitigation strategy development\n\n**Risk Assessment Framework Example**:\n```\nConduct a risk assessment for the launch of our new mobile application, focusing on:\n1. Technical Risks: Potential failures, performance issues, compatibility problems\n2. Market Risks: Competitor responses, user adoption challenges, pricing concerns\n3. Operational Risks: Support demands, scalability issues, maintenance requirements\n4. Compliance Risks: Data privacy, regulatory requirements, industry standards\nFor each identified risk:\n- Rate probability (Low/Medium/High)\n- Assess potential impact (Low/Medium/High)\n- Suggest a specific mitigation strategy\n- Identify an early warning indicator\nPrioritize the top 3 risks that require immediate attention and detailed mitigation plans.\n```\n\nThese decision support applications show how LLMs can be used to provide structured, balanced analysis for complex decision-making processes.",
            type: "application",
            order: 3,
            pointsReward: 30,
            estimatedMinutes: 25
          }
        ];
      } else if (moduleNumber === 4) {
        lessonData = [
          {
            title: "Structured Testing Approaches",
            description: "Learn systematic methods for testing and improving your prompts",
            content: "# Structured Testing Approaches\n\nEffective prompt engineering requires systematic testing. This lesson explores structured approaches to testing and improving your prompts.\n\n## Defining Success Criteria\n\nBefore you can effectively test prompts, you need clear metrics for success:\n- Establishing clear metrics for prompt performance\n- Balancing multiple objectives\n- Creating evaluation rubrics\n\n**Evaluation Rubric Example**:\n```\nContent Generation Evaluation Rubric:\n\n| Criterion | 1 (Poor) | 3 (Acceptable) | 5 (Excellent) |\n|-----------|----------|----------------|---------------|\n| Relevance to Brief | Misses key requirements | Addresses most requirements | Fully addresses all requirements |\n| Factual Accuracy | Contains multiple errors | Generally accurate with minor issues | Completely accurate |\n| Tone Alignment | Inconsistent or inappropriate tone | Mostly consistent with target tone | Perfect tone alignment |\n| Structure & Flow | Disorganized, hard to follow | Logical structure with minor flow issues | Perfectly structured with excellent flow |\n| Engagement | Dull, generic content | Reasonably engaging | Highly engaging and compelling |\n```\n\n## Controlled Variation Testing\n\nSystematic testing helps isolate what works and what doesn't:\n- Systematic prompt modification techniques\n- A/B testing methodologies for prompts\n- Isolating variables for targeted improvement\n\n**Systematic Testing Process**:\n1. Create a baseline prompt\n2. Identify one element to modify (instruction clarity, examples, constraints)\n3. Create 2-3 variations changing only that element\n4. Test with identical inputs\n5. Evaluate results against success criteria\n6. Implement winning approach and repeat\n\n## Documenting Prompt Performance\n\nTracking and documenting your prompts helps build institutional knowledge:\n- Creating effective prompt libraries\n- Version control for prompt development\n- Performance tracking over time\n\n**Prompt Documentation Template Example**:\n```\nPrompt ID: PR-2023-05\nVersion: 1.3\nPurpose: Generate weekly project status reports\nContext included: Yes, project background and goals\nExamples included: Yes, 2 sample reports\nOutput format: Markdown with specific headings\nPerformance metrics:\n- Completion rate: 98%\n- Accuracy: 92%\n- User satisfaction: 4.2/5\nKnown limitations: Struggles with technical jargon in engineering projects\n```\n\nBy implementing these structured testing approaches, you can systematically improve your prompts and build a valuable library of effective prompting techniques for your specific use cases.",
            type: "methodology",
            order: 1,
            pointsReward: 30,
            estimatedMinutes: 25
          },
          {
            title: "Common Failure Modes & Solutions",
            description: "Identify and address common issues that cause LLMs to produce undesired results",
            content: "# Common Failure Modes & Solutions\n\nEven well-crafted prompts can sometimes fail to produce the desired results. This lesson explores common failure modes and how to address them.\n\n## Managing Hallucinations and Inaccuracies\n\nUnderstanding why LLMs hallucinate helps you prevent and address inaccuracies:\n\n**Root causes**:\n- Ambiguous instructions\n- Missing context\n- Asking for information beyond model knowledge\n\n**Solutions**:\n- Ground responses in provided information\n- Request confidence levels or source attribution\n- Break complex tasks into verifiable steps\n- Implement human verification for critical information\n\n**Hallucination-Resistant Example**:\n```\nBased ONLY on the information in our annual report that I've provided, summarize our company's market position.\nIf any important information seems missing for this analysis, please specifically identify what additional data would be helpful.\n```\n\n## Addressing Refusals and Safety Filters\n\nUnderstanding model limitations helps you work within their constraints:\n- Understanding model limitations and policies\n- Reformulating requests appropriately\n- Finding alternative approaches to tasks\n\n**Policy-Compliant Alternative Example**:\n```\nInstead of: \"Write content that impersonates our CEO.\"\nTry: \"Help me draft talking points in our CEO's communication style based on these previous company announcements.\"\n```\n\n## Fixing Inconsistent Outputs\n\nUnderstanding the sources of variability helps you create more consistent prompts:\n\n**Sources of variability**:\n- Temperature settings\n- Ambiguous instructions\n- Competing objectives\n\n**Stabilization techniques**:\n- Use explicit formatting requirements\n- Provide clear evaluation criteria\n- Implement few-shot examples for consistent patterns\n- Reduce temperature settings for more deterministic outputs\n\n**Consistency Improvement Example**:\n```\nProvide EXACTLY 5 recommendations for improving our e-commerce website's conversion rate.\nFor each recommendation:\n1. State the specific issue\n2. Explain why it matters to users\n3. Suggest a concrete implementation approach\n4. Estimate the level of effort required (low/medium/high)\nFormat each recommendation as a separate numbered section with appropriate subheadings.\n```\n\nBy understanding these common failure modes and implementing appropriate solutions, you can significantly improve the reliability and consistency of your LLM outputs.",
            type: "troubleshooting",
            order: 2,
            pointsReward: 30,
            estimatedMinutes: 25
          },
          {
            title: "Building a Continuous Improvement Process",
            description: "Develop systems for ongoing refinement and optimization of your prompts",
            content: "# Building a Continuous Improvement Process\n\nEffective prompt engineering is an ongoing process, not a one-time effort. This lesson explores how to implement a continuous improvement process for your prompts.\n\n## Implementing Feedback Loops\n\nSystematic feedback collection improves prompt performance over time:\n- User feedback collection methods\n- Automated performance monitoring\n- Periodic review processes\n\n**Feedback Collection Framework**:\n- Direct User Feedback: Ratings, comments, success/failure reporting\n- Performance Metrics: Completion rates, response times, edit requirements\n- Usage Patterns: Most/least used prompts, abandonment rates, retries\n\n## Prompt Versioning and Iteration\n\nManaging prompt versions allows for controlled improvement:\n- Prompt versioning systems\n- A/B testing methodologies\n- Documenting changes and improvements\n\n**Prompt Iteration Log Example**:\n```\nPrompt: Customer Support Email Generator\nVersion 1.0 (2023-01-15): Initial implementation\nVersion 1.1 (2023-02-03): Added tone guidelines to improve consistency\nVersion 1.2 (2023-03-20): Implemented structured format with clear sections\nVersion 2.0 (2023-05-12): Complete rewrite using few-shot learning approach\n- Improvement: Response relevance increased from 72% to 88%\n- Improvement: Editor satisfaction rating increased from 3.2/5 to 4.5/5\n```\n\n## Adapting to Model Updates\n\nLLM capabilities evolve rapidly, requiring prompt adaptation:\n- Monitoring model changes and updates\n- Testing prompts against new model versions\n- Leveraging new capabilities as they emerge\n\n**Model Update Adaptation Process**:\n1. Monitor provider announcements for model updates\n2. Test core prompts against updated models\n3. Identify performance changes (improvements or regressions)\n4. Adjust prompts to leverage new capabilities or address regressions\n5. Document model-specific variations when necessary\n\n## Building Organizational Knowledge\n\nPrompt engineering expertise should be shared across teams:\n- Creating prompt engineering guidelines\n- Building shared prompt libraries\n- Training team members on effective techniques\n\n**Knowledge Sharing Approaches**:\n- Prompt Engineering Playbooks: Documented best practices and patterns\n- Internal Workshops: Training sessions for teams and new employees\n- Shared Repositories: Centralized collection of effective prompts and templates\n- Case Studies: Documentation of successful implementations and lessons learned\n\nBy implementing these continuous improvement processes, you'll develop more effective prompts over time and build valuable institutional knowledge about prompt engineering within your organization.",
            type: "process",
            order: 3,
            pointsReward: 30,
            estimatedMinutes: 25
          }
        ];
      }
      for (const lesson of lessonData) {
        const existingLesson = existingLessons.find((l) => l.order === lesson.order);
        if (existingLesson) {
          console.log(`Updating lesson "${lesson.title}" (ID: ${existingLesson.id})`);
          await db.update(learningLessons3).set({
            title: lesson.title,
            description: lesson.description,
            content: lesson.content,
            type: lesson.type,
            pointsReward: lesson.pointsReward,
            estimatedMinutes: lesson.estimatedMinutes
          }).where(eq8(learningLessons3.id, existingLesson.id));
        } else {
          console.log(`Creating new lesson "${lesson.title}" for module ID ${moduleId}`);
          const [newLesson] = await db.insert(learningLessons3).values({
            moduleId,
            title: lesson.title,
            description: lesson.description,
            content: lesson.content,
            type: lesson.type,
            order: lesson.order,
            pointsReward: lesson.pointsReward,
            estimatedMinutes: lesson.estimatedMinutes
          }).returning();
          console.log(`Creating challenge for lesson "${lesson.title}" (ID: ${newLesson.id})`);
          let challengeData = {
            lessonId: newLesson.id,
            title: `${lesson.title} Challenge`,
            description: `Apply your knowledge of ${lesson.title.toLowerCase()}`,
            prompt: `Based on what you've learned about ${lesson.title.toLowerCase()}, create a practical example that demonstrates your understanding.`,
            criteria: JSON.stringify([
              { type: "contains", rule: "key concepts", points: 10 },
              { type: "contains", rule: "practical application", points: 10 },
              { type: "length", rule: "250", points: 5 }
            ]),
            difficulty: 2,
            pointsReward: 25
          };
          if (lesson.title.includes("How LLMs Work")) {
            challengeData.prompt = "Explain the concept of tokens and context windows in your own words, and describe a practical situation where understanding these concepts would help you create more effective prompts.";
          } else if (lesson.title.includes("Major LLM Players")) {
            challengeData.prompt = "Compare and contrast two different LLM providers, highlighting their unique strengths and limitations. Then describe a specific use case where one would be preferable over the other.";
          } else if (lesson.title.includes("Prompt Anatomy")) {
            challengeData.prompt = "Take this vague prompt: 'Write about our company' and transform it into a well-structured prompt with clear context, task definition, and output specifications.";
          } else if (lesson.title.includes("Prompt Patterns")) {
            challengeData.prompt = "Create examples of the same request using different prompt patterns: role-based, step-by-step, and few-shot learning. Explain which pattern you think would work best for this particular task and why.";
          } else if (lesson.title.includes("Content Generation")) {
            challengeData.prompt = "Design a detailed prompt template for a recurring business communication (weekly updates, client pitches, etc.). Your template should include clear structure requirements, content elements, tone guidance, and length parameters.";
          } else if (lesson.title.includes("Testing Approaches")) {
            challengeData.prompt = "Design a controlled experiment to test three variations of a prompt for a specific business task. Describe your methodology, evaluation criteria, and how you would document the results.";
          }
          await db.insert(learningChallenges3).values(challengeData);
        }
      }
    }
  });
  app2.get("/api/admin/add-missing-modules", async (req, res) => {
    try {
      const { eq: eq8 } = await import("drizzle-orm");
      const { learningPaths: learningPaths3, learningModules: learningModules3 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
      const pathId = 2;
      const [path3] = await db.select().from(learningPaths3).where(eq8(learningPaths3.id, pathId));
      if (!path3) {
        return res.json({ message: "Learning path not found." });
      }
      const existingModules = await db.select().from(learningModules3).where(eq8(learningModules3.pathId, pathId));
      console.log(`Found ${existingModules.length} existing modules for path "${path3.title}"`);
      const moduleNames = [
        "Foundations of Effective Prompt Engineering",
        "Advanced Prompting Techniques",
        "Iterative Refinement and Optimization",
        "Real-World Applications and Integration"
      ];
      const createdModules = [];
      for (let i = 0; i < moduleNames.length; i++) {
        const moduleName = moduleNames[i];
        const moduleExists = existingModules.some((m) => m.title === moduleName);
        if (moduleExists) {
          console.log(`Module "${moduleName}" already exists, skipping.`);
          continue;
        }
        console.log(`Creating missing module "${moduleName}"`);
        let moduleData = {
          pathId: 1,
          title: moduleName,
          description: "",
          order: 0,
          requiredPoints: 0,
          estimatedHours: 2,
          bannerImage: ""
        };
        if (moduleName.includes("Foundations")) {
          moduleData = {
            pathId,
            title: moduleName,
            order: i + 1,
            requiredPoints: 0,
            estimatedHours: 2,
            description: "Learn the core principles of effective prompt design, understand prompt components, and recognize differences across major LLM providers.",
            bannerImage: "https://images.unsplash.com/photo-1617791160505-6f00504e3519?q=80&w=2940&auto=format&fit=crop"
          };
        } else if (moduleName.includes("Advanced")) {
          moduleData = {
            pathId,
            title: moduleName,
            order: i + 1,
            requiredPoints: 0,
            estimatedHours: 2,
            description: "Master zero-shot and few-shot prompting, chain-of-thought reasoning, persona-based prompting, and effective use of delimiters.",
            bannerImage: "https://images.unsplash.com/photo-1655720033654-a4239dd42d10?q=80&w=2940&auto=format&fit=crop"
          };
        } else if (moduleName.includes("Refinement")) {
          moduleData = {
            pathId,
            title: moduleName,
            order: i + 1,
            requiredPoints: 0,
            estimatedHours: 2,
            description: "Learn the art of prompt debugging, refinement, and testing for optimal results across different scenarios.",
            bannerImage: "https://images.unsplash.com/photo-1688891982748-830800e5833f?q=80&w=2940&auto=format&fit=crop"
          };
        } else if (moduleName.includes("Applications")) {
          moduleData = {
            pathId,
            title: moduleName,
            order: i + 1,
            requiredPoints: 0,
            estimatedHours: 2,
            description: "Discover how to apply prompt engineering in various domains and create cohesive prompt systems for real-world applications.",
            bannerImage: "https://images.unsplash.com/photo-1638571447486-ed5a87abcc4f?q=80&w=3032&auto=format&fit=crop"
          };
        }
        const [newModule] = await db.insert(learningModules3).values(moduleData).returning();
        createdModules.push(newModule);
      }
      return res.json({
        message: "Successfully added missing modules",
        createdModules: createdModules.length,
        modules: createdModules.map((m) => m.title)
      });
    } catch (error) {
      console.error("Error adding missing modules:", error);
      res.status(500).json({ error: "Failed to add missing modules" });
    }
  });
  app2.get("/api/admin/add-lessons-to-modules", async (req, res) => {
    try {
      const { eq: eq8 } = await import("drizzle-orm");
      const { learningModules: learningModules3, learningLessons: learningLessons3, learningChallenges: learningChallenges3 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
      const modules = await db.select().from(learningModules3).where(eq8(learningModules3.pathId, 2));
      if (modules.length === 0) {
        return res.json({ message: "No modules found for the learning path." });
      }
      console.log(`Found ${modules.length} modules for the learning path.`);
      const createdLessons = [];
      const createdChallenges = [];
      const module2 = modules.find((m) => m.title.includes("Advanced Prompting Techniques"));
      if (module2) {
        console.log(`Adding lessons to module "${module2.title}" (ID: ${module2.id})`);
        const existingLessons = await db.select().from(learningLessons3).where(eq8(learningLessons3.moduleId, module2.id));
        if (existingLessons.length > 0) {
          console.log(`Module already has ${existingLessons.length} lessons, skipping.`);
        } else {
          const lesson2_1 = await db.insert(learningLessons3).values({
            moduleId: module2.id,
            title: "Zero-Shot and Few-Shot Prompting",
            description: "Master techniques for getting quality results with minimal examples",
            content: "# Zero-Shot and Few-Shot Prompting\n\nThese techniques allow language models to perform tasks with limited or no specific examples.\n\n## Zero-Shot Prompting\n\nZero-shot prompting involves asking the model to perform a task without any demonstrations. This relies on the model's pre-training knowledge.\n\n## Few-Shot Prompting\n\nFew-shot prompting provides the model with a small number of examples to guide its responses, improving accuracy for specialized tasks.\n\n## Practical Applications\n\nThese techniques are particularly useful when:\n- Working with new or uncommon tasks\n- You have limited examples to work with\n- Testing a model's capabilities quickly",
            type: "technique",
            order: 1,
            pointsReward: 30,
            estimatedMinutes: 25
          }).returning();
          createdLessons.push(lesson2_1[0]);
          const lesson2_2 = await db.insert(learningLessons3).values({
            moduleId: module2.id,
            title: "Chain-of-Thought Reasoning",
            description: "Learn how to guide AI through complex reasoning processes step by step",
            content: '# Chain-of-Thought Reasoning\n\nChain-of-Thought (CoT) is a prompting technique that encourages language models to break down complex problems into a series of intermediate steps.\n\n## Benefits of CoT\n\n- Improves accuracy on logical and mathematical tasks\n- Creates more transparent reasoning processes\n- Helps avoid common reasoning errors\n\n## Implementation Techniques\n\n1. **Explicit CoT**: Directly asking the model to "think step by step"\n2. **Demonstrated CoT**: Providing examples that show the reasoning process\n3. **Self-Consistency CoT**: Generating multiple reasoning paths and selecting the most consistent answer',
            type: "technique",
            order: 2,
            pointsReward: 30,
            estimatedMinutes: 25
          }).returning();
          createdLessons.push(lesson2_2[0]);
          const challenge2 = await db.insert(learningChallenges3).values({
            lessonId: lesson2_1[0].id,
            title: "Few-Shot Prompt Construction",
            description: "Create an effective few-shot prompt for a specialized task",
            prompt: "Create a few-shot prompt to teach an AI to generate fictional but scientifically plausible alien species descriptions. Include 2-3 examples in your prompt that demonstrate the desired format and content.",
            criteria: JSON.stringify([
              { type: "contains", rule: "clear instruction", points: 5 },
              { type: "contains", rule: "example format", points: 10 },
              { type: "contains", rule: "consistent pattern", points: 10 },
              { type: "length", rule: "300", points: 5 }
            ]),
            difficulty: 3,
            pointsReward: 40
          }).returning();
          createdChallenges.push(challenge2[0]);
        }
      }
      const module1 = modules.find((m) => m.title.includes("Foundations of Effective Prompt Engineering"));
      if (module1) {
        console.log(`Adding lessons to module "${module1.title}" (ID: ${module1.id})`);
        const existingLessons = await db.select().from(learningLessons3).where(eq8(learningLessons3.moduleId, module1.id));
        if (existingLessons.length > 0) {
          console.log(`Module already has ${existingLessons.length} lessons, skipping.`);
        } else {
          const lesson1_1 = await db.insert(learningLessons3).values({
            moduleId: module1.id,
            title: "The Evolution of Prompt Engineering",
            description: "Understand how prompt engineering has developed from basic queries to a sophisticated discipline",
            content: "# The Evolution of Prompt Engineering\n\nPrompt engineering has evolved significantly since the introduction of modern LLMs. This lesson explores the historical context and development of the field.\n\n## Early Beginnings\n\nPrompt engineering started with simple query-response patterns but quickly evolved as language models became more sophisticated.\n\n## Key Milestones\n\n1. Basic instruction prompts\n2. Introduction of few-shot examples\n3. Development of chain-of-thought techniques\n4. Creation of specialized frameworks for different tasks\n\n## Current State\n\nToday, prompt engineering is recognized as a critical skill for effective AI utilization, with specialized techniques for different domains and use cases.",
            type: "theory",
            order: 1,
            pointsReward: 20,
            estimatedMinutes: 15
          }).returning();
          createdLessons.push(lesson1_1[0]);
          const lesson1_2 = await db.insert(learningLessons3).values({
            moduleId: module1.id,
            title: "Core Components of Effective Prompts",
            description: "Learn about the essential elements that make up well-structured, effective prompts",
            content: "# Core Components of Effective Prompts\n\nA well-crafted prompt consists of several key components that work together to generate the desired output.\n\n## Essential Elements\n\n1. **Clear Context**: Providing relevant background information\n2. **Specific Instructions**: Explicit directions on what to generate\n3. **Role Assignment**: Defining the AI's perspective or expertise\n4. **Format Specifications**: How the response should be structured\n5. **Examples**: Demonstrations of expected inputs and outputs\n\n## Balancing Components\n\nThe art of prompt engineering involves balancing these elements based on your specific needs.",
            type: "theory",
            order: 2,
            pointsReward: 25,
            estimatedMinutes: 20
          }).returning();
          createdLessons.push(lesson1_2[0]);
          const challenge1 = await db.insert(learningChallenges3).values({
            lessonId: lesson1_1[0].id,
            title: "Prompt Evolution Analysis",
            description: "Analyze and compare different generations of prompts",
            prompt: "Analyze these three prompts and explain how they represent different stages of prompt engineering evolution: 1) 'Write about climate change' 2) 'Write a 500-word article about climate change impacts on agriculture' 3) 'As an environmental scientist specializing in agricultural impacts, write a structured 500-word analysis of climate change effects on crop yields in temperate regions. Include data trends, adaptation strategies, and future projections.'",
            criteria: JSON.stringify([
              { type: "contains", rule: "evolution stages", points: 10 },
              { type: "contains", rule: "specificity analysis", points: 10 },
              { type: "contains", rule: "improvement suggestions", points: 10 }
            ]),
            difficulty: 2,
            pointsReward: 30
          }).returning();
          createdChallenges.push(challenge1[0]);
        }
      }
      const module3 = modules.find((m) => m.title.includes("Iterative Refinement"));
      if (module3) {
        console.log(`Adding lessons to module "${module3.title}" (ID: ${module3.id})`);
        const existingLessons = await db.select().from(learningLessons3).where(eq8(learningLessons3.moduleId, module3.id));
        if (existingLessons.length > 0) {
          console.log(`Module already has ${existingLessons.length} lessons, skipping.`);
        } else {
          const lesson3_1 = await db.insert(learningLessons3).values({
            moduleId: module3.id,
            title: "Prompt Debugging Strategies",
            description: "Learn systematic approaches to identify and fix issues in your prompts",
            content: "# Prompt Debugging Strategies\n\nWhen prompts don't produce the expected results, systematic debugging approaches can help identify and resolve issues.\n\n## Common Prompt Issues\n\n1. **Ambiguity**: Unclear or vague instructions\n2. **Conflicting Instructions**: Contradictory guidance\n3. **Inadequate Context**: Missing important information\n4. **Format Problems**: Unclear structure requirements\n\n## Debugging Process\n\n1. Isolate the problematic sections of your prompt\n2. Test variations to pinpoint specific issues\n3. Apply incremental improvements\n4. Document what works and what doesn't",
            type: "practical",
            order: 1,
            pointsReward: 35,
            estimatedMinutes: 30
          }).returning();
          createdLessons.push(lesson3_1[0]);
          const lesson3_2 = await db.insert(learningLessons3).values({
            moduleId: module3.id,
            title: "A/B Testing for Prompt Optimization",
            description: "Apply systematic testing methods to compare and improve different prompt variations",
            content: "# A/B Testing for Prompt Optimization\n\nSystematic testing allows you to compare different prompt variations and determine which performs best for your specific use case.\n\n## Setting Up Effective Tests\n\n1. Define clear success metrics\n2. Create controlled prompt variations\n3. Use consistent evaluation methods\n4. Collect sufficient samples for statistical significance\n\n## Analysis Techniques\n\n- Compare qualitative and quantitative metrics\n- Identify patterns across different prompt structures\n- Document findings for future prompt development",
            type: "practical",
            order: 2,
            pointsReward: 35,
            estimatedMinutes: 30
          }).returning();
          createdLessons.push(lesson3_2[0]);
          const challenge3 = await db.insert(learningChallenges3).values({
            lessonId: lesson3_1[0].id,
            title: "Prompt Debugging Exercise",
            description: "Identify and fix issues in a problematic prompt",
            prompt: "This prompt has multiple issues: 'create content that's engaging but also professional while being comprehensive yet concise and include all important details without being too lengthy make it appropriate for beginners and experts.' Identify at least three specific problems with this prompt and provide a corrected version that resolves these issues.",
            criteria: JSON.stringify([
              { type: "contains", rule: "problem identification", points: 15 },
              { type: "contains", rule: "solution implementation", points: 15 },
              { type: "contains", rule: "improved structure", points: 10 }
            ]),
            difficulty: 3,
            pointsReward: 40
          }).returning();
          createdChallenges.push(challenge3[0]);
        }
      }
      const module4 = modules.find((m) => m.title.includes("Real-World Applications"));
      if (module4) {
        console.log(`Adding lessons to module "${module4.title}" (ID: ${module4.id})`);
        const existingLessons = await db.select().from(learningLessons3).where(eq8(learningLessons3.moduleId, module4.id));
        if (existingLessons.length > 0) {
          console.log(`Module already has ${existingLessons.length} lessons, skipping.`);
        } else {
          const lesson4_1 = await db.insert(learningLessons3).values({
            moduleId: module4.id,
            title: "Domain-Specific Prompt Engineering",
            description: "Learn how to customize prompts for specific industries and use cases",
            content: "# Domain-Specific Prompt Engineering\n\nDifferent domains require specialized prompt approaches to achieve optimal results.\n\n## Industry-Specific Considerations\n\n- **Healthcare**: Managing sensitive information and medical terminology\n- **Legal**: Ensuring precision and adherence to specific formats\n- **Creative**: Balancing guidance with creative freedom\n- **Technical**: Incorporating domain expertise and technical requirements\n\n## Adaptation Strategies\n\n1. Research domain-specific terminology and conventions\n2. Consult with subject matter experts\n3. Build domain-specific prompt libraries\n4. Develop evaluation criteria relevant to the domain",
            type: "application",
            order: 1,
            pointsReward: 40,
            estimatedMinutes: 35
          }).returning();
          createdLessons.push(lesson4_1[0]);
          const lesson4_2 = await db.insert(learningLessons3).values({
            moduleId: module4.id,
            title: "Building Comprehensive Prompt Systems",
            description: "Design interconnected prompt frameworks for complex applications",
            content: "# Building Comprehensive Prompt Systems\n\nComplex applications often require multiple interconnected prompts working together as a coherent system.\n\n## System Architecture\n\n1. **Input Processing**: Preparing and normalizing user inputs\n2. **Prompt Routing**: Directing queries to appropriate specialized prompts\n3. **Response Generation**: Creating the primary content\n4. **Post-Processing**: Refining and formatting the final output\n\n## Implementation Considerations\n\n- Establish consistent interfaces between system components\n- Create robust error handling and fallback mechanisms\n- Design for extensibility and maintenance\n- Implement feedback loops for continuous improvement",
            type: "application",
            order: 2,
            pointsReward: 40,
            estimatedMinutes: 35
          }).returning();
          createdLessons.push(lesson4_2[0]);
          const challenge4 = await db.insert(learningChallenges3).values({
            lessonId: lesson4_1[0].id,
            title: "Domain-Specific Prompt Development",
            description: "Create a specialized prompt for a specific industry",
            prompt: "Develop a detailed prompt for generating financial investment advice. Your prompt should include appropriate disclaimers, ensure balanced perspective, require specific information inputs, and produce structured, professional output suitable for financial advisors to review before sharing with clients.",
            criteria: JSON.stringify([
              { type: "contains", rule: "domain terminology", points: 10 },
              { type: "contains", rule: "appropriate disclaimers", points: 10 },
              { type: "contains", rule: "structured format", points: 10 },
              { type: "contains", rule: "information requirements", points: 10 }
            ]),
            difficulty: 4,
            pointsReward: 50
          }).returning();
          createdChallenges.push(challenge4[0]);
        }
      }
      return res.json({
        message: "Successfully added lessons to modules",
        lessonCount: createdLessons.length,
        challengeCount: createdChallenges.length
      });
    } catch (error) {
      console.error("Error adding lessons to modules:", error);
      res.status(500).json({ error: "Failed to add lessons to modules" });
    }
  });
  app2.get("/api/admin/cleanup-learning-paths", async (req, res) => {
    try {
      const { eq: eq8 } = await import("drizzle-orm");
      const { learningPaths: learningPaths3, learningModules: learningModules3, learningLessons: learningLessons3, learningChallenges: learningChallenges3 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
      const pathTitle = "From Beginner to Intermediate: LLM Prompt Engineering";
      const paths = await db.select().from(learningPaths3).where(eq8(learningPaths3.title, pathTitle));
      if (paths.length <= 1) {
        return res.json({ message: "No duplicate learning paths found." });
      }
      console.log(`Found ${paths.length} instances of learning path "${pathTitle}". Keeping only the first one.`);
      paths.sort((a, b) => a.id - b.id);
      const keepPathId = paths[0].id;
      const deletePathIds = paths.slice(1).map((p) => p.id);
      console.log(`Keeping path ID ${keepPathId}, deleting path IDs: ${deletePathIds.join(", ")}`);
      for (const pathId of deletePathIds) {
        const modules = await db.select().from(learningModules3).where(eq8(learningModules3.pathId, pathId));
        for (const module of modules) {
          const lessons = await db.select().from(learningLessons3).where(eq8(learningLessons3.moduleId, module.id));
          for (const lesson of lessons) {
            await db.delete(learningChallenges3).where(eq8(learningChallenges3.lessonId, lesson.id));
          }
          await db.delete(learningLessons3).where(eq8(learningLessons3.moduleId, module.id));
        }
        await db.delete(learningModules3).where(eq8(learningModules3.pathId, pathId));
        await db.delete(learningPaths3).where(eq8(learningPaths3.id, pathId));
      }
      res.json({
        message: "Successfully cleaned up duplicate learning paths",
        pathsRemoved: deletePathIds.length,
        remainingPath: keepPathId
      });
    } catch (error) {
      console.error("Error cleaning up duplicate learning paths:", error);
      res.status(500).json({ error: "Failed to clean up duplicate learning paths" });
    }
  });
  app2.post("/api/enhance", async (req, res) => {
    let responseSent = false;
    const userId = req.isAuthenticated() ? req.user.id : null;
    if (userId && !req.body.settings?.directAccess) {
      try {
        const usageStatus = await UsageTrackingService.trackPromptEnhancement(userId, false);
        if (!usageStatus.success && usageStatus.limitReached) {
          return res.status(402).json({
            error: "Free tier limit reached",
            message: "You have reached your monthly limit of free prompt enhancements.",
            currentUsage: usageStatus.currentUsage,
            maxUsage: usageStatus.maxUsage,
            limitReached: true
          });
        }
      } catch (error) {
        console.error("Error checking usage limits:", error);
      }
    }
    const requestTimeout = setTimeout(() => {
      if (!responseSent) {
        responseSent = true;
        console.log("Request timeout reached, sending fallback response");
        res.status(504).json({
          message: "Request timed out",
          fallbackUsed: true
        });
      }
    }, 2e4);
    try {
      const schema = z2.object({
        originalPrompt: z2.string().min(1),
        useCase: z2.string(),
        settings: z2.object({
          model: z2.string(),
          creativity: z2.string(),
          tone: z2.string(),
          format: z2.string(),
          framework: z2.string().default("general"),
          personaId: z2.number().nullable().optional(),
          artisticStyle: z2.string().optional(),
          directAccess: z2.boolean().optional()
          // New flag for direct model access
        })
      });
      const data = schema.parse(req.body);
      const useDirectAccess = data.settings.directAccess === true;
      console.log(`Enhancing prompt using model: ${data.settings.model}, useCase: ${data.useCase}, directAccess: ${useDirectAccess}`);
      console.log("Request body settings:", JSON.stringify(data.settings, null, 2));
      let enhancementResult;
      try {
        if (useDirectAccess && process.env.OPENROUTER_API_KEY) {
          const { enhancePromptDirect: enhancePromptDirect2 } = await Promise.resolve().then(() => (init_direct_api(), direct_api_exports));
          enhancementResult = await enhancePromptDirect2(
            data.originalPrompt,
            data.useCase,
            data.settings
          );
          console.log(`Successfully enhanced prompt with Direct API (${data.settings.model})`);
        } else if (data.settings.model === "gemini") {
          enhancementResult = await enhancePromptWithGemini(
            data.originalPrompt,
            data.useCase,
            data.settings
          );
          console.log("Successfully enhanced prompt with Gemini");
        } else if (["claude", "mistral", "llama"].includes(data.settings.model) && process.env.OPENROUTER_API_KEY) {
          enhancementResult = await enhancePromptWithOpenRouter(
            data.originalPrompt,
            data.useCase,
            data.settings
          );
          console.log(`Successfully enhanced prompt with Open Router (${data.settings.model})`);
        } else {
          console.log(`Using template-based enhancement for model: ${data.settings.model}`);
          const useCaseTemplates = {
            "content": "I need you to act as a professional content strategist with expertise in digital marketing. Create a comprehensive outline for a blog post about [TOPIC]. The blog should target [AUDIENCE] who are interested in [INTEREST]. Include SEO keywords, recommended headings (H2, H3), estimated word count per section, and suggestions for visual elements. The tone should be [TONE] and the goal is to [GOAL].",
            "business": "I need you to act as a professional business writer with expertise in corporate communications. Create a structured [DOCUMENT_TYPE] (report/proposal/memo) addressing [BUSINESS_ISSUE] for [TARGET_AUDIENCE] (executives/stakeholders/employees). Include: 1) Executive summary with key findings, 2) Background and context, 3) Analysis with supporting data, 4) Strategic recommendations with implementation steps, 5) Financial implications, and 6) Next steps with timeline. Maintain a professional tone and focus on actionable business outcomes. Use appropriate business terminology and formatting.",
            "product": "I need you to act as a Senior Product Manager creating a detailed [DOCUMENT_TYPE] (PRD/roadmap/user story/feature spec) for [PRODUCT_NAME]. Include: 1) Problem statement and user needs, 2) Proposed solution with clear success metrics, 3) User personas and journeys, 4) Detailed functional and non-functional requirements, 5) Dependencies and constraints, 6) Timeline with milestones, 7) Risks and mitigation strategies, and 8) Success criteria for measuring impact. Write with clarity, precision, and a focus on user value while addressing business objectives.",
            "marketing": "I need you to act as a Digital Marketing Strategist creating a comprehensive [CAMPAIGN_TYPE] campaign plan for [PRODUCT/SERVICE]. Include: 1) Target audience analysis with detailed personas, 2) Channel strategy across paid, owned and earned media, 3) Content plan with messaging framework, 4) Campaign timeline with key deliverables, 5) Budget allocation across channels, 6) KPIs and performance tracking methodology, and 7) A/B testing approach for optimization. Focus on conversion-driven strategies with clear ROI measurement. Use data-driven insights and current digital marketing best practices.",
            "research": "I need a detailed research analysis on [TOPIC]. Please include: 1) Historical context and evolution, 2) Current state and leading theories, 3) Key debates and controversies, 4) Future directions and emerging trends, 5) Practical applications in [FIELD], and 6) Comprehensive bibliography of seminal works. Focus especially on peer-reviewed research from the last 5 years.",
            "creative": "Create a compelling short story in the [GENRE] genre with the following elements: a protagonist who is [CHARACTER TRAIT], a setting that involves [SETTING], and a central conflict about [CONFLICT]. The story should have an unexpected twist and convey the theme of [THEME]. Use vivid sensory details and varied sentence structure. Aim for approximately 1000 words with a clear beginning, middle, and end.",
            "technical": "Create comprehensive technical documentation for [TECHNOLOGY/PRODUCT]. Include: 1) Overview and architecture, 2) Installation requirements and procedure, 3) Configuration options with examples, 4) API endpoints with request/response formats, 5) Common error codes and troubleshooting, 6) Security best practices, and 7) Performance optimization guidelines. Use clear, concise language appropriate for developers with intermediate experience.",
            "image-generation": `Create a detailed and highly descriptive prompt for generating an image of [SUBJECT] in ${data.settings.artisticStyle || "photorealistic"} style. Please include: 1) Specific visual characteristics (colors, textures, lighting, perspective), 2) Style specifications focusing on ${data.settings.artisticStyle || "photorealistic"} aesthetics, 3) Spatial relationships and composition (foreground, background, positioning), 4) Emotional tone or mood to convey, 5) Details about setting or environment, and 6) Any technical parameters (aspect ratio, resolution quality, rendering style). Use vivid, visual language that clearly communicates the desired outcome.`
          };
          const enhancedPrompt = useCaseTemplates[data.useCase] || "Create a detailed prompt about [TOPIC] with specific instructions, structure, and clear goals.";
          enhancementResult = {
            enhancedPrompt,
            improvements: [
              "Added specific structure with clear sections",
              "Included placeholders for key variables that you should customize",
              "Enhanced specificity with numbered lists and clear organization"
            ],
            fallbackUsed: !process.env.OPENROUTER_API_KEY
          };
        }
      } catch (enhanceError) {
        console.error("Error in enhancement process:", enhanceError);
        const useCaseTemplates = {
          "content": "I need you to act as a professional content strategist with expertise in digital marketing. Create a comprehensive outline for a blog post about [TOPIC]. The blog should target [AUDIENCE] who are interested in [INTEREST]. Include SEO keywords, recommended headings (H2, H3), estimated word count per section, and suggestions for visual elements. The tone should be [TONE] and the goal is to [GOAL].",
          "business": "I need you to act as a professional business writer with expertise in corporate communications. Create a structured [DOCUMENT_TYPE] (report/proposal/memo) addressing [BUSINESS_ISSUE] for [TARGET_AUDIENCE] (executives/stakeholders/employees). Include: 1) Executive summary with key findings, 2) Background and context, 3) Analysis with supporting data, 4) Strategic recommendations with implementation steps, 5) Financial implications, and 6) Next steps with timeline. Maintain a professional tone and focus on actionable business outcomes. Use appropriate business terminology and formatting.",
          "product": "I need you to act as a Senior Product Manager creating a detailed [DOCUMENT_TYPE] (PRD/roadmap/user story/feature spec) for [PRODUCT_NAME]. Include: 1) Problem statement and user needs, 2) Proposed solution with clear success metrics, 3) User personas and journeys, 4) Detailed functional and non-functional requirements, 5) Dependencies and constraints, 6) Timeline with milestones, 7) Risks and mitigation strategies, and 8) Success criteria for measuring impact. Write with clarity, precision, and a focus on user value while addressing business objectives.",
          "marketing": "I need you to act as a Digital Marketing Strategist creating a comprehensive [CAMPAIGN_TYPE] campaign plan for [PRODUCT/SERVICE]. Include: 1) Target audience analysis with detailed personas, 2) Channel strategy across paid, owned and earned media, 3) Content plan with messaging framework, 4) Campaign timeline with key deliverables, 5) Budget allocation across channels, 6) KPIs and performance tracking methodology, and 7) A/B testing approach for optimization. Focus on conversion-driven strategies with clear ROI measurement. Use data-driven insights and current digital marketing best practices.",
          "research": "I need a detailed research analysis on [TOPIC]. Please include: 1) Historical context and evolution, 2) Current state and leading theories, 3) Key debates and controversies, 4) Future directions and emerging trends, 5) Practical applications in [FIELD], and 6) Comprehensive bibliography of seminal works. Focus especially on peer-reviewed research from the last 5 years.",
          "creative": "Create a compelling short story in the [GENRE] genre with the following elements: a protagonist who is [CHARACTER TRAIT], a setting that involves [SETTING], and a central conflict about [CONFLICT]. The story should have an unexpected twist and convey the theme of [THEME]. Use vivid sensory details and varied sentence structure. Aim for approximately 1000 words with a clear beginning, middle, and end.",
          "technical": "Create comprehensive technical documentation for [TECHNOLOGY/PRODUCT]. Include: 1) Overview and architecture, 2) Installation requirements and procedure, 3) Configuration options with examples, 4) API endpoints with request/response formats, 5) Common error codes and troubleshooting, 6) Security best practices, and 7) Performance optimization guidelines. Use clear, concise language appropriate for developers with intermediate experience.",
          "image-generation": `Create a detailed and highly descriptive prompt for generating an image of [SUBJECT] in ${data.settings.artisticStyle || "photorealistic"} style. Please include: 1) Specific visual characteristics (colors, textures, lighting, perspective), 2) Style specifications focusing on ${data.settings.artisticStyle || "photorealistic"} aesthetics, 3) Spatial relationships and composition (foreground, background, positioning), 4) Emotional tone or mood to convey, 5) Details about setting or environment, and 6) Any technical parameters (aspect ratio, resolution quality, rendering style). Use vivid, visual language that clearly communicates the desired outcome.`
        };
        const enhancedPrompt = useCaseTemplates[data.useCase] || "Create a detailed prompt about [TOPIC] with specific instructions, structure, and clear goals.";
        enhancementResult = {
          enhancedPrompt,
          improvements: [
            "Added specific structure with clear sections",
            "Included placeholders for key variables that you should customize",
            "Enhanced specificity with numbered lists and clear organization"
          ],
          fallbackUsed: true
        };
      }
      clearTimeout(requestTimeout);
      if (!responseSent) {
        responseSent = true;
        if (req.isAuthenticated() && req.user) {
          try {
            const { recordPromptUsage: recordPromptUsage2 } = await Promise.resolve().then(() => (init_usage_limits(), usage_limits_exports));
            recordPromptUsage2(req.user.id).catch((error) => {
              console.error("Error recording prompt usage:", error);
            });
          } catch (error) {
            console.error("Error importing usage-limits module:", error);
          }
        }
        res.json(enhancementResult);
      }
    } catch (error) {
      clearTimeout(requestTimeout);
      console.error("Error enhancing prompt:", error);
      if (!responseSent) {
        responseSent = true;
        if (error instanceof z2.ZodError) {
          res.status(400).json({ message: "Invalid request data", errors: error.errors });
        } else {
          res.status(500).json({
            message: "Error enhancing prompt",
            error: String(error),
            fallbackUsed: true
          });
        }
      }
    } finally {
      clearTimeout(requestTimeout);
    }
  });
  app2.post("/api/prompts", async (req, res) => {
    try {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ message: "You must be logged in to save prompts" });
      }
      const data = insertPromptSchema.parse({
        ...req.body,
        userId: req.user.id,
        // Ensure settings is properly stored as JSON
        settings: typeof req.body.settings === "string" ? JSON.parse(req.body.settings) : req.body.settings || {}
      });
      const prompt = await storage.createPrompt(data);
      if (data.isPublic) {
        console.log(`User ${req.user.id} shared a prompt to the public library`);
      }
      res.json(prompt);
    } catch (error) {
      console.error("Error creating prompt:", error);
      res.status(400).json({ message: "Invalid prompt data" });
    }
  });
  app2.get("/api/prompts", async (_req, res) => {
    try {
      const prompts2 = await storage.getAllPrompts();
      res.json(prompts2);
    } catch (error) {
      console.error("Error getting prompts:", error);
      res.status(500).json({ message: "Error retrieving prompts" });
    }
  });
  app2.get("/api/prompts/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const prompt = await storage.getPrompt(id);
      if (!prompt) {
        return res.status(404).json({ message: "Prompt not found" });
      }
      res.json(prompt);
    } catch (error) {
      console.error("Error getting prompt:", error);
      res.status(500).json({ message: "Error retrieving prompt" });
    }
  });
  app2.get("/api/public-prompts", async (_req, res) => {
    try {
      const prompts2 = await storage.getPublicPrompts();
      res.json(prompts2);
    } catch (error) {
      console.error("Error getting public prompts:", error);
      res.status(500).json({ message: "Error retrieving public prompts" });
    }
  });
  app2.get("/api/user-prompts", async (req, res) => {
    try {
      const userId = req.isAuthenticated() ? req.user.id : null;
      const prompts2 = await storage.getUserPrompts(userId);
      res.json(prompts2);
    } catch (error) {
      console.error("Error getting user prompts:", error);
      res.status(500).json({ message: "Error retrieving user prompts" });
    }
  });
  app2.get("/api/search-prompts", async (req, res) => {
    try {
      const { query } = req.query;
      if (!query || typeof query !== "string") {
        return res.status(400).json({ message: "Search query is required" });
      }
      const prompts2 = await storage.searchPublicPrompts(query);
      res.json(prompts2);
    } catch (error) {
      console.error("Error searching prompts:", error);
      res.status(500).json({ message: "Error searching prompts" });
    }
  });
  app2.post("/api/prompts/:id/upvote", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const prompt = await storage.upvotePrompt(id);
      if (!prompt) {
        return res.status(404).json({ message: "Prompt not found" });
      }
      res.json(prompt);
    } catch (error) {
      console.error("Error upvoting prompt:", error);
      res.status(500).json({ message: "Error upvoting prompt" });
    }
  });
  app2.get("/api/prompts/:id/comments", async (req, res) => {
    try {
      const promptId = parseInt(req.params.id);
      const comments = await storage.getPromptComments(promptId);
      res.json(comments);
    } catch (error) {
      console.error("Error getting prompt comments:", error);
      res.status(500).json({ message: "Error retrieving prompt comments" });
    }
  });
  app2.post("/api/prompts/:id/comments", async (req, res) => {
    try {
      const promptId = parseInt(req.params.id);
      const prompt = await storage.getPrompt(promptId);
      if (!prompt) {
        return res.status(404).json({ message: "Prompt not found" });
      }
      const commentData = insertPromptCommentSchema.parse({
        ...req.body,
        promptId
      });
      const comment = await storage.createPromptComment(commentData);
      res.status(201).json(comment);
    } catch (error) {
      console.error("Error creating comment:", error);
      if (error instanceof z2.ZodError) {
        res.status(400).json({ message: "Invalid comment data", errors: error.errors });
      } else {
        res.status(500).json({ message: "Error creating comment" });
      }
    }
  });
  app2.delete("/api/comments/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const success = await storage.deletePromptComment(id);
      if (!success) {
        return res.status(404).json({ message: "Comment not found" });
      }
      res.json({ success: true });
    } catch (error) {
      console.error("Error deleting comment:", error);
      res.status(500).json({ message: "Error deleting comment" });
    }
  });
  app2.post("/api/templates", async (req, res) => {
    try {
      const data = insertTemplateSchema.parse(req.body);
      const template = await storage.createTemplate(data);
      res.json(template);
    } catch (error) {
      console.error("Error creating template:", error);
      res.status(400).json({ message: "Invalid template data" });
    }
  });
  app2.get("/api/templates", async (_req, res) => {
    try {
      const templates2 = await storage.getTemplates();
      res.json(templates2);
    } catch (error) {
      console.error("Error getting templates:", error);
      res.status(500).json({ message: "Error retrieving templates" });
    }
  });
  app2.get("/api/templates/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const template = await storage.getTemplate(id);
      if (!template) {
        return res.status(404).json({ message: "Template not found" });
      }
      res.json(template);
    } catch (error) {
      console.error("Error getting template:", error);
      res.status(500).json({ message: "Error retrieving template" });
    }
  });
  app2.patch("/api/templates/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const data = insertTemplateSchema.partial().parse(req.body);
      const template = await storage.updateTemplate(id, data);
      if (!template) {
        return res.status(404).json({ message: "Template not found" });
      }
      res.json(template);
    } catch (error) {
      console.error("Error updating template:", error);
      res.status(400).json({ message: "Invalid template data" });
    }
  });
  app2.delete("/api/templates/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const success = await storage.deleteTemplate(id);
      if (!success) {
        return res.status(404).json({ message: "Template not found" });
      }
      res.json({ success: true });
    } catch (error) {
      console.error("Error deleting template:", error);
      res.status(500).json({ message: "Error deleting template" });
    }
  });
  app2.post("/api/knowledge", async (req, res) => {
    try {
      const data = insertPromptKnowledgeSchema.parse(req.body);
      const knowledge = await storage.createPromptKnowledge(data);
      res.json(knowledge);
    } catch (error) {
      console.error("Error creating prompt knowledge entry:", error);
      res.status(400).json({ message: "Invalid prompt knowledge data" });
    }
  });
  app2.get("/api/knowledge", async (req, res) => {
    try {
      const { category, useCase, query } = req.query;
      let knowledge;
      if (category && typeof category === "string") {
        knowledge = await storage.getPromptKnowledgeByCategory(category);
      } else if (useCase && typeof useCase === "string") {
        knowledge = await storage.getPromptKnowledgeByUseCase(useCase);
      } else if (query && typeof query === "string") {
        knowledge = await storage.searchPromptKnowledge(query);
      } else {
        knowledge = await storage.getAllPromptKnowledge();
      }
      res.json(knowledge);
    } catch (error) {
      console.error("Error getting prompt knowledge:", error);
      res.status(500).json({ message: "Error retrieving prompt knowledge" });
    }
  });
  app2.get("/api/knowledge/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const knowledge = await storage.getPromptKnowledge(id);
      if (!knowledge) {
        return res.status(404).json({ message: "Prompt knowledge entry not found" });
      }
      res.json(knowledge);
    } catch (error) {
      console.error("Error getting prompt knowledge entry:", error);
      res.status(500).json({ message: "Error retrieving prompt knowledge entry" });
    }
  });
  app2.patch("/api/knowledge/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const data = insertPromptKnowledgeSchema.partial().parse(req.body);
      const updatedKnowledge = await storage.updatePromptKnowledge(id, data);
      if (!updatedKnowledge) {
        return res.status(404).json({ message: "Prompt knowledge entry not found" });
      }
      res.json(updatedKnowledge);
    } catch (error) {
      console.error("Error updating prompt knowledge entry:", error);
      if (error instanceof z2.ZodError) {
        res.status(400).json({ message: "Invalid prompt knowledge data", errors: error.errors });
      } else {
        res.status(500).json({ message: "Error updating prompt knowledge entry" });
      }
    }
  });
  app2.delete("/api/knowledge/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const success = await storage.deletePromptKnowledge(id);
      if (!success) {
        return res.status(404).json({ message: "Prompt knowledge entry not found" });
      }
      res.json({ success: true });
    } catch (error) {
      console.error("Error deleting prompt knowledge entry:", error);
      res.status(500).json({ message: "Error deleting prompt knowledge entry" });
    }
  });
  app2.get("/api/personas/templates", async (_req, res) => {
    try {
      const templates2 = getPersonaTemplates();
      res.json(templates2);
    } catch (error) {
      console.error("Error getting persona templates:", error);
      res.status(500).json({ message: "Error retrieving persona templates" });
    }
  });
  app2.post("/api/personas/generate", async (req, res) => {
    try {
      let responseSent = false;
      const requestTimeout = setTimeout(() => {
        if (!responseSent) {
          responseSent = true;
          console.log("Persona generation request timeout reached, sending fallback response");
          res.status(504).json({
            message: "Request timed out",
            fallbackUsed: true
          });
        }
      }, 3e4);
      const schema = z2.object({
        concept: z2.string().min(1, "Concept is required"),
        primaryUseCase: z2.string().optional(),
        tone: z2.string().optional(),
        model: z2.string(),
        openRouterModel: z2.string().optional()
      });
      const data = schema.parse(req.body);
      console.log(`Generating persona using model: ${data.model}, concept: ${data.concept}`);
      const generatedPersona = await generatePersona(data);
      clearTimeout(requestTimeout);
      if (!responseSent) {
        responseSent = true;
        res.json(generatedPersona);
      }
    } catch (error) {
      console.error("Error generating persona:", error);
      if (error instanceof z2.ZodError) {
        res.status(400).json({ message: "Invalid request data", errors: error.errors });
      } else {
        res.status(500).json({ message: `Error generating persona: ${error.message || "Unknown error"}` });
      }
    }
  });
  app2.post("/api/personas", async (req, res) => {
    try {
      const data = insertPersonaSchema.parse(req.body);
      const persona = await storage.createPersona(data);
      res.json(persona);
    } catch (error) {
      console.error("Error creating persona:", error);
      if (error instanceof z2.ZodError) {
        res.status(400).json({ message: "Invalid persona data", errors: error.errors });
      } else {
        res.status(400).json({ message: "Invalid persona data" });
      }
    }
  });
  app2.get("/api/personas", async (req, res) => {
    try {
      const userId = req.isAuthenticated() ? req.user.id : null;
      let personas2;
      if (req.query.public === "true") {
        personas2 = await storage.getPublicPersonas();
      } else {
        personas2 = await storage.getUserPersonas(userId);
      }
      res.json(personas2);
    } catch (error) {
      console.error("Error getting personas:", error);
      res.status(500).json({ message: "Error retrieving personas" });
    }
  });
  app2.get("/api/personas/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const persona = await storage.getPersona(id);
      if (!persona) {
        return res.status(404).json({ message: "Persona not found" });
      }
      res.json(persona);
    } catch (error) {
      console.error("Error getting persona:", error);
      res.status(500).json({ message: "Error retrieving persona" });
    }
  });
  app2.patch("/api/personas/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const data = insertPersonaSchema.partial().parse(req.body);
      const persona = await storage.updatePersona(id, data);
      if (!persona) {
        return res.status(404).json({ message: "Persona not found" });
      }
      res.json(persona);
    } catch (error) {
      console.error("Error updating persona:", error);
      if (error instanceof z2.ZodError) {
        res.status(400).json({ message: "Invalid persona data", errors: error.errors });
      } else {
        res.status(400).json({ message: "Invalid persona data" });
      }
    }
  });
  app2.delete("/api/personas/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const success = await storage.deletePersona(id);
      if (!success) {
        return res.status(404).json({ message: "Persona not found" });
      }
      res.json({ success: true });
    } catch (error) {
      console.error("Error deleting persona:", error);
      res.status(500).json({ message: "Error deleting persona" });
    }
  });
  app2.get("/api/admin/fix-learning-path-images", async (req, res) => {
    try {
      const { eq: eq8 } = await import("drizzle-orm");
      const { learningPaths: learningPaths3 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
      const [promptEngineeringPath] = await db.select().from(learningPaths3).where(eq8(learningPaths3.title, "From Beginner to Intermediate: LLM Prompt Engineering"));
      if (promptEngineeringPath) {
        await db.update(learningPaths3).set({
          bannerImage: "https://images.unsplash.com/photo-1620712943543-bcc4688e7485?q=80&w=2942&auto=format&fit=crop"
        }).where(eq8(learningPaths3.id, promptEngineeringPath.id));
        console.log(`Updated image for "${promptEngineeringPath.title}"`);
      }
      const [fundamentalsPath] = await db.select().from(learningPaths3).where(eq8(learningPaths3.title, "Prompt Engineering Fundamentals"));
      if (fundamentalsPath) {
        await db.update(learningPaths3).set({
          bannerImage: "https://images.unsplash.com/photo-1677442135136-760c813028c0?q=80&w=2832&auto=format&fit=crop"
        }).where(eq8(learningPaths3.id, fundamentalsPath.id));
        console.log(`Updated image for "${fundamentalsPath.title}"`);
      }
      res.json({ message: "Successfully updated learning path images" });
    } catch (error) {
      console.error("Error updating learning path images:", error);
      res.status(500).json({ error: "Failed to update learning path images" });
    }
  });
  app2.get("/api/learning-paths", async (_req, res) => {
    try {
      const paths = await storage.getLearningPaths();
      res.json(paths);
    } catch (error) {
      console.error("Error getting learning paths:", error);
      res.status(500).json({ message: "Error retrieving learning paths" });
    }
  });
  app2.get("/api/learning-paths/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const path3 = await storage.getLearningPath(id);
      if (!path3) {
        return res.status(404).json({ message: "Learning path not found" });
      }
      res.json(path3);
    } catch (error) {
      console.error("Error getting learning path:", error);
      res.status(500).json({ message: "Error retrieving learning path" });
    }
  });
  app2.get("/api/learning-paths/:pathId/modules", async (req, res) => {
    try {
      const pathId = parseInt(req.params.pathId);
      const path3 = await storage.getLearningPath(pathId);
      if (!path3) {
        return res.status(404).json({ message: "Learning path not found" });
      }
      const modules = await storage.getLearningModules(pathId);
      res.json(modules);
    } catch (error) {
      console.error("Error getting learning modules:", error);
      res.status(500).json({ message: "Error retrieving learning modules" });
    }
  });
  app2.get("/api/learning-modules/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const module = await storage.getLearningModule(id);
      if (!module) {
        return res.status(404).json({ message: "Learning module not found" });
      }
      res.json(module);
    } catch (error) {
      console.error("Error getting learning module:", error);
      res.status(500).json({ message: "Error retrieving learning module" });
    }
  });
  app2.get("/api/learning-modules/:moduleId/lessons", async (req, res) => {
    try {
      const moduleId = parseInt(req.params.moduleId);
      const module = await storage.getLearningModule(moduleId);
      if (!module) {
        return res.status(404).json({ message: "Learning module not found" });
      }
      const lessons = await storage.getLearningLessons(moduleId);
      res.json(lessons);
    } catch (error) {
      console.error("Error getting learning lessons:", error);
      res.status(500).json({ message: "Error retrieving learning lessons" });
    }
  });
  app2.get("/api/learning-lessons/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const lesson = await storage.getLearningLesson(id);
      if (!lesson) {
        return res.status(404).json({ message: "Learning lesson not found" });
      }
      res.json(lesson);
    } catch (error) {
      console.error("Error getting learning lesson:", error);
      res.status(500).json({ message: "Error retrieving learning lesson" });
    }
  });
  app2.get("/api/learning-lessons/:lessonId/challenges", async (req, res) => {
    try {
      const lessonId = parseInt(req.params.lessonId);
      const lesson = await storage.getLearningLesson(lessonId);
      if (!lesson) {
        return res.status(404).json({ message: "Learning lesson not found" });
      }
      const challenges = await storage.getLearningChallenges(lessonId);
      res.json(challenges);
    } catch (error) {
      console.error("Error getting learning challenges:", error);
      res.status(500).json({ message: "Error retrieving learning challenges" });
    }
  });
  app2.get("/api/learning-challenges/:id", async (req, res) => {
    try {
      const id = parseInt(req.params.id);
      const challenge = await storage.getLearningChallenge(id);
      if (!challenge) {
        return res.status(404).json({ message: "Learning challenge not found" });
      }
      res.json(challenge);
    } catch (error) {
      console.error("Error getting learning challenge:", error);
      res.status(500).json({ message: "Error retrieving learning challenge" });
    }
  });
  app2.post("/api/learning-challenges/:id/submit", async (req, res) => {
    try {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ message: "You must be logged in to submit a challenge" });
      }
      const challengeId = parseInt(req.params.id);
      const { submission } = req.body;
      if (!submission || typeof submission !== "string") {
        return res.status(400).json({ message: "Submission is required" });
      }
      const challenge = await storage.getLearningChallenge(challengeId);
      if (!challenge) {
        return res.status(404).json({ message: "Learning challenge not found" });
      }
      const result = {
        success: true,
        points: 25,
        feedback: "Great job completing this challenge!"
      };
      if (result.success) {
        const { db: db2 } = await Promise.resolve().then(() => (init_db(), db_exports));
        const { userCompletions: userCompletions3 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
        await db2.insert(userCompletions3).values({
          userId: req.user.id,
          challengeId,
          pointsEarned: result.points,
          userNotes: submission
        });
      }
      res.json(result);
    } catch (error) {
      console.error("Error submitting challenge:", error);
      res.status(500).json({ message: "Error processing challenge submission" });
    }
  });
  app2.post("/api/learning-lessons/:id/complete", async (req, res) => {
    try {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ message: "You must be logged in to complete a lesson" });
      }
      const lessonId = parseInt(req.params.id);
      const lesson = await storage.getLearningLesson(lessonId);
      if (!lesson) {
        return res.status(404).json({ message: "Learning lesson not found" });
      }
      const { db: db2 } = await Promise.resolve().then(() => (init_db(), db_exports));
      const { userCompletions: userCompletions3 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
      const completion = await db2.insert(userCompletions3).values({
        userId: req.user.id,
        lessonId,
        pointsEarned: lesson.pointsReward || 10,
        // Default if not set
        userNotes: null
      }).returning();
      res.json({ success: true, completion });
    } catch (error) {
      console.error("Error completing lesson:", error);
      res.status(500).json({ message: "Error recording lesson completion" });
    }
  });
  app2.get("/api/user/learning-progress", async (req, res) => {
    try {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ message: "You must be logged in to view your progress" });
      }
      const paths = await storage.getLearningPaths();
      const progress = await Promise.all(
        paths.map(
          (path3) => storage.getUserProgress(req.user.id, path3.id).catch(() => null)
        )
      );
      const validProgress = progress.filter((p) => p !== null);
      res.json(validProgress);
    } catch (error) {
      console.error("Error getting user learning progress:", error);
      res.status(500).json({ message: "Error retrieving learning progress" });
    }
  });
  app2.get("/api/user/learning-progress/:pathId", async (req, res) => {
    try {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ message: "You must be logged in to view your progress" });
      }
      const pathId = parseInt(req.params.pathId);
      const progress = await storage.getUserProgress(req.user.id, pathId);
      if (!progress) {
        return res.json({
          userId: req.user.id,
          pathId,
          currentModuleId: null,
          currentLessonId: null,
          pointsEarned: 0,
          modulesCompleted: 0,
          lessonsCompleted: 0,
          challengesCompleted: 0,
          isCompleted: false
        });
      }
      res.json(progress);
    } catch (error) {
      console.error("Error getting user learning progress for path:", error);
      res.status(500).json({ message: "Error retrieving learning progress" });
    }
  });
  app2.get("/api/user/completions", async (req, res) => {
    try {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ message: "You must be logged in to view your completions" });
      }
      const { db: db2 } = await Promise.resolve().then(() => (init_db(), db_exports));
      const { userCompletions: userCompletions3 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
      const { eq: eq8 } = await import("drizzle-orm");
      const completions = await db2.select().from(userCompletions3).where(eq8(userCompletions3.userId, req.user.id));
      res.json(completions);
    } catch (error) {
      console.error("Error getting user completions:", error);
      res.status(500).json({ message: "Error retrieving user completions" });
    }
  });
  app2.get("/api/badges", async (_req, res) => {
    try {
      const badges3 = await storage.getAllBadges();
      res.json(badges3);
    } catch (error) {
      console.error("Error getting badges:", error);
      res.status(500).json({ message: "Error retrieving badges" });
    }
  });
  app2.get("/api/user/badges", async (req, res) => {
    try {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ message: "You must be logged in to view your badges" });
      }
      const userBadges3 = await storage.getUserBadges(req.user.id);
      res.json(userBadges3);
    } catch (error) {
      console.error("Error getting user badges:", error);
      res.status(500).json({ message: "Error retrieving user badges" });
    }
  });
  if (stripe2) {
    app2.post("/api/create-payment-intent", async (req, res) => {
      try {
        const { amount, description } = req.body;
        if (!req.isAuthenticated()) {
          return res.status(401).json({ message: "Authentication required" });
        }
        const paymentIntent = await stripe2.paymentIntents.create({
          amount: Math.round(amount * 100),
          // Convert dollars to cents
          currency: "usd",
          metadata: {
            userId: String(req.user.id),
            description: description || "Prompt Engineering Pro"
          }
        });
        res.json({ clientSecret: paymentIntent.client_secret });
      } catch (error) {
        console.error("Error creating payment intent:", error);
        res.status(500).json({
          message: "Error creating payment intent",
          error: error.message
        });
      }
    });
    const requireAuth = (req, res, next) => {
      const isApiRequest = req.path.startsWith("/api/");
      if (!req.isAuthenticated()) {
        if (isApiRequest) {
          res.setHeader("Content-Type", "application/json");
          return res.status(401).json({
            error: "Authentication required",
            code: "AUTH_REQUIRED"
          });
        } else {
          return res.redirect("/auth");
        }
      }
      const user = req.user;
      if (!user || !user.id) {
        if (isApiRequest) {
          res.setHeader("Content-Type", "application/json");
          return res.status(400).json({
            error: "Invalid user data in session",
            code: "INVALID_USER_SESSION"
          });
        } else {
          return res.redirect("/auth?error=invalid_session");
        }
      }
      next();
    };
    app2.post("/api/create-subscription", requireAuth, async (req, res) => {
      try {
        const user = req.user;
        let customerId = user.stripeCustomerId;
        if (!customerId) {
          const customer = await stripe2.customers.create({
            email: user.email,
            name: user.username,
            metadata: {
              userId: String(user.id)
            }
          });
          customerId = customer.id;
          await storage.updateUser(user.id, { stripeCustomerId: customerId });
        }
        const { priceId } = req.body;
        if (!priceId) {
          return res.status(400).json({ message: "Price ID is required" });
        }
        const subscription = await stripe2.subscriptions.create({
          customer: customerId,
          items: [{ price: priceId }],
          payment_behavior: "default_incomplete",
          expand: ["latest_invoice.payment_intent"]
        });
        await storage.updateUser(user.id, {
          stripeSubscriptionId: subscription.id,
          subscriptionStatus: subscription.status
        });
        const invoice = subscription.latest_invoice;
        const checkoutSession = await stripe2.checkout.sessions.create({
          payment_method_types: ["card"],
          customer: customerId,
          line_items: [
            {
              price: priceId,
              quantity: 1
            }
          ],
          mode: "subscription",
          success_url: `${req.headers.origin || "https://enhance-my-prompt.replit.app"}/dashboard?success=true`,
          cancel_url: `${req.headers.origin || "https://enhance-my-prompt.replit.app"}/dashboard?canceled=true`
        });
        res.json({
          subscriptionId: subscription.id,
          clientSecret: invoice.payment_intent?.client_secret,
          checkoutUrl: checkoutSession.url
        });
      } catch (error) {
        console.error("Error creating subscription:", error);
        res.status(500).json({
          message: "Error creating subscription",
          error: error.message
        });
      }
    });
    app2.post("/api/webhook", express.raw({ type: "application/json" }), async (req, res) => {
      let event;
      try {
        console.log("Stripe webhook received:", {
          signature: !!req.headers["stripe-signature"],
          body: typeof req.body === "string" ? "string" : "parsed",
          eventType: req.body?.type
        });
        const signature = req.headers["stripe-signature"];
        if (!process.env.STRIPE_WEBHOOK_SECRET) {
          console.error("Missing STRIPE_WEBHOOK_SECRET - webhook verification disabled");
          return res.status(500).json({ error: "Webhook configuration error" });
        }
        event = stripe2.webhooks.constructEvent(
          req.body,
          signature,
          process.env.STRIPE_WEBHOOK_SECRET
        );
        console.log("Webhook event verified:", {
          type: event.type,
          objectId: event.data.object.id
        });
        switch (event.type) {
          case "customer.subscription.created":
          case "customer.subscription.updated": {
            const subscription = event.data.object;
            const customerId = subscription.customer;
            const [user] = await db.select().from(users).where(eq6(users.stripeCustomerId, customerId));
            if (user) {
              await db.update(users).set({
                stripeSubscriptionId: subscription.id,
                subscriptionStatus: subscription.status,
                subscriptionTier: subscription.status === "active" ? "pro" : "free",
                subscriptionExpiresAt: subscription.cancel_at ? new Date(subscription.cancel_at * 1e3) : null
              }).where(eq6(users.id, user.id));
              console.log(`Updated subscription for user ${user.id}:`, {
                status: subscription.status,
                tier: subscription.status === "active" ? "pro" : "free"
              });
            } else {
              console.error("No user found for customer:", customerId);
            }
            break;
          }
          case "customer.subscription.deleted": {
            const subscription = event.data.object;
            const customerId = subscription.customer;
            const [user] = await db.select().from(users).where(eq6(users.stripeCustomerId, customerId));
            if (user) {
              await db.update(users).set({
                subscriptionStatus: "canceled",
                subscriptionTier: "free",
                subscriptionExpiresAt: /* @__PURE__ */ new Date()
              }).where(eq6(users.id, user.id));
              console.log(`Subscription canceled for user ${user.id}`);
            } else {
              console.error("No user found for customer:", customerId);
            }
            break;
          }
          case "invoice.payment_succeeded": {
            const invoice = event.data.object;
            const customerId = invoice.customer;
            const [user] = await db.select().from(users).where(eq6(users.stripeCustomerId, customerId));
            if (user) {
              await db.update(users).set({
                subscriptionStatus: "active",
                subscriptionTier: "pro"
              }).where(eq6(users.id, user.id));
              console.log(`Payment succeeded for user ${user.id}`);
            }
            break;
          }
          case "invoice.payment_failed": {
            const invoice = event.data.object;
            const customerId = invoice.customer;
            const [user] = await db.select().from(users).where(eq6(users.stripeCustomerId, customerId));
            if (user) {
              await db.update(users).set({
                subscriptionStatus: "past_due"
              }).where(eq6(users.id, user.id));
              console.log(`Payment failed for user ${user.id}`);
            }
            break;
          }
        }
        res.json({ received: true });
      } catch (error) {
        console.error("Webhook error:", error);
        return res.status(400).json({
          error: "Webhook Error",
          message: error instanceof Error ? error.message : "Unknown error"
        });
      }
    });
    app2.get("/api/user/usage", requireAuth, async (req, res) => {
      res.setHeader("Content-Type", "application/json");
      try {
        const user = req.user;
        if (!user?.id) {
          return res.status(401).json({
            error: "Authentication required",
            message: "User not authenticated",
            code: "AUTH_REQUIRED"
          });
        }
        const { getRemainingPrompts: getRemainingPrompts2 } = await Promise.resolve().then(() => (init_usage_limits(), usage_limits_exports));
        const usageData = await getRemainingPrompts2(user.id);
        return res.json({
          used: usageData.used,
          limit: usageData.limit,
          remaining: usageData.remaining,
          nextResetDate: new Date(usageData.nextResetDate).toISOString(),
          isUnlimited: usageData.isUnlimited
        });
      } catch (error) {
        console.error("Error in /api/user/usage:", error);
        return res.status(500).json({
          error: "Internal server error",
          message: error instanceof Error ? error.message : "Unknown error",
          code: "INTERNAL_ERROR"
        });
      }
    });
    app2.get("/api/subscription", requireAuth, async (req, res) => {
      try {
        const user = req.user;
        if (!user.stripeSubscriptionId) {
          return res.json({ active: false });
        }
        const subscription = await stripe2.subscriptions.retrieve(user.stripeSubscriptionId);
        if (!subscription || typeof subscription !== "object" || !("status" in subscription)) {
          throw new Error("Invalid subscription data received from Stripe");
        }
        res.json({
          active: subscription.status === "active",
          status: subscription.status,
          currentPeriodEnd: new Date(subscription.current_period_end * 1e3),
          subscriptionId: subscription.id,
          priceId: subscription.items.data[0].price.id
        });
      } catch (error) {
        console.error("Error getting subscription:", error);
        res.status(500).json({
          message: "Error getting subscription",
          error: error.message
        });
      }
    });
    app2.post("/api/cancel-subscription", requireAuth, async (req, res) => {
      try {
        const user = req.user;
        if (!user.stripeSubscriptionId) {
          return res.status(400).json({ message: "No active subscription" });
        }
        const subscription = await stripe2.subscriptions.update(user.stripeSubscriptionId, {
          cancel_at_period_end: true
        });
        const subscriptionData = subscription;
        res.json({
          canceled: true,
          cancelAtPeriodEnd: subscriptionData.cancel_at_period_end,
          currentPeriodEnd: new Date(subscriptionData.current_period_end * 1e3)
        });
      } catch (error) {
        console.error("Error canceling subscription:", error);
        res.status(500).json({
          message: "Error canceling subscription",
          error: error.message
        });
      }
    });
  }
  app2.get("/api/auth/check", (req, res) => {
    res.setHeader("Content-Type", "application/json");
    if (!req.isAuthenticated()) {
      return res.status(401).json({
        error: "Not authenticated",
        code: "AUTH_REQUIRED"
      });
    }
    return res.json({
      authenticated: true,
      user: {
        id: req.user.id,
        email: req.user.email,
        subscriptionTier: req.user.subscriptionTier,
        subscriptionStatus: req.user.subscriptionStatus
      }
    });
  });
  app2.get("/api/admin/fix-db-schema", async (req, res) => {
    try {
      if (!req.isAuthenticated()) {
        return res.status(401).json({ error: "Authentication required" });
      }
      const { addMissingUsageColumns: addMissingUsageColumns2 } = await Promise.resolve().then(() => (init_add_missing_usage_columns(), add_missing_usage_columns_exports));
      const result = await addMissingUsageColumns2();
      if (result) {
        res.status(200).json({ success: true, message: "Database schema updated successfully" });
      } else {
        res.status(500).json({ success: false, message: "Failed to update database schema" });
      }
    } catch (error) {
      console.error("Error running migration:", error);
      res.status(500).json({
        success: false,
        message: "Error running migration",
        error: error instanceof Error ? error.message : String(error)
      });
    }
  });
  app2.get("/api/admin/test-usage", async (req, res) => {
    try {
      if (process.env.NODE_ENV === "production" && !req.isAuthenticated()) {
        return res.status(401).json({ error: "Authentication required" });
      }
      const userId = req.isAuthenticated() ? req.user.id : 1;
      const { and: and4, eq: eq8 } = await import("drizzle-orm");
      const { userUsage: userUsage2 } = await Promise.resolve().then(() => (init_schema(), schema_exports));
      const [existingUsage] = await db.select().from(userUsage2).where(eq8(userUsage2.userId, userId));
      if (existingUsage) {
        const [updatedUsage] = await db.update(userUsage2).set({
          enhancedPromptsCount: existingUsage.enhancedPromptsCount + 1,
          generatedPersonasCount: existingUsage.generatedPersonasCount + 1,
          updatedAt: /* @__PURE__ */ new Date()
        }).where(eq8(userUsage2.id, existingUsage.id)).returning();
        return res.json({
          success: true,
          message: "Updated existing usage record",
          before: existingUsage,
          after: updatedUsage
        });
      } else {
        const [newUsage] = await db.insert(userUsage2).values({
          userId,
          promptsUsed: 0,
          promptsLimit: 5,
          lastResetDate: /* @__PURE__ */ new Date(),
          nextResetDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1e3),
          createdAt: /* @__PURE__ */ new Date(),
          updatedAt: /* @__PURE__ */ new Date(),
          enhancedPromptsCount: 1,
          generatedPersonasCount: 1
        }).returning();
        return res.json({
          success: true,
          message: "Created new usage record",
          usage: newUsage
        });
      }
    } catch (error) {
      console.error("Error testing usage:", error);
      return res.status(500).json({
        success: false,
        message: "Error testing usage tracking",
        error: error instanceof Error ? error.message : String(error)
      });
    }
  });
  const httpServer = createServer(app2);
  return httpServer;
}

// server/vite.ts
import express2 from "express";
import fs from "fs";
import path2 from "path";
import { createServer as createViteServer, createLogger } from "vite";

// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import themePlugin from "@replit/vite-plugin-shadcn-theme-json";
import path from "path";
import runtimeErrorOverlay from "@replit/vite-plugin-runtime-error-modal";
var vite_config_default = defineConfig({
  plugins: [
    react(),
    runtimeErrorOverlay(),
    themePlugin(),
    ...process.env.NODE_ENV !== "production" && process.env.REPL_ID !== void 0 ? [
      await import("@replit/vite-plugin-cartographer").then(
        (m) => m.cartographer()
      )
    ] : []
  ],
  server: {
    allowedHosts: [
      "2cf460ec-e960-4989-9f66-9fc93e788942-00-2dc4q027lgbyq.picard.replit.dev"
    ]
  },
  resolve: {
    alias: {
      "@": path.resolve(import.meta.dirname, "client", "src"),
      "@shared": path.resolve(import.meta.dirname, "shared"),
      "@assets": path.resolve(import.meta.dirname, "attached_assets")
    }
  },
  root: path.resolve(import.meta.dirname, "client"),
  build: {
    outDir: path.resolve(import.meta.dirname, "dist/public"),
    emptyOutDir: true
  }
});

// server/vite.ts
import { nanoid } from "nanoid";
var viteLogger = createLogger();
function log(message, source = "express") {
  const formattedTime = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", {
    hour: "numeric",
    minute: "2-digit",
    second: "2-digit",
    hour12: true
  });
  console.log(`${formattedTime} [${source}] ${message}`);
}
async function setupVite(app2, server) {
  const serverOptions = {
    middlewareMode: true,
    hmr: { server },
    allowedHosts: [
      "2cf460ec-e960-4989-9f66-9fc93e788942-00-2dc4q027lgbyq.picard.replit.dev"
    ]
  };
  const vite = await createViteServer({
    ...vite_config_default,
    configFile: false,
    customLogger: {
      ...viteLogger,
      error: (msg, options) => {
        viteLogger.error(msg, options);
        process.exit(1);
      }
    },
    server: serverOptions,
    appType: "custom"
  });
  app2.use(vite.middlewares);
  app2.use("*", async (req, res, next) => {
    const url = req.originalUrl;
    try {
      const clientTemplate = path2.resolve(
        import.meta.dirname,
        "..",
        "client",
        "index.html"
      );
      let template = await fs.promises.readFile(clientTemplate, "utf-8");
      template = template.replace(
        `src="/src/main.tsx"`,
        `src="/src/main.tsx?v=${nanoid()}"`
      );
      const page = await vite.transformIndexHtml(url, template);
      res.status(200).set({ "Content-Type": "text/html" }).end(page);
    } catch (e) {
      vite.ssrFixStacktrace(e);
      next(e);
    }
  });
}
function serveStatic(app2) {
  const distPath = path2.resolve(import.meta.dirname, "public");
  if (!fs.existsSync(distPath)) {
    throw new Error(
      `Could not find the build directory: ${distPath}, make sure to build the client first`
    );
  }
  app2.use(express2.static(distPath));
  app2.use("*", (_req, res) => {
    res.sendFile(path2.resolve(distPath, "index.html"));
  });
}

// server/index.ts
import cors from "cors";

// server/cron.ts
init_db();
init_schema();
import { CronJob } from "cron";
import { addMonths, format, startOfMonth } from "date-fns";
import { eq as eq7 } from "drizzle-orm";
async function resetMonthlyUsage() {
  try {
    console.log("Starting monthly usage reset job...");
    const today = /* @__PURE__ */ new Date();
    const lastResetDate = format(today, "yyyy-MM-dd");
    const nextResetDate = format(addMonths(startOfMonth(today), 1), "yyyy-MM-dd");
    const result = await db.update(userUsage).set({
      promptsUsed: 0,
      lastResetDate,
      nextResetDate,
      updatedAt: today
    }).where(
      eq7(userUsage.nextResetDate, format(startOfMonth(today), "yyyy-MM-dd"))
    ).returning();
    console.log(`Reset ${result.length} usage records`);
  } catch (error) {
    console.error("Error in monthly usage reset job:", error);
  }
}
async function cleanupOrphanedRecords() {
  try {
    console.log("Starting orphaned records cleanup job...");
    const { rowCount } = await db.execute(
      `DELETE FROM user_usage 
       WHERE NOT EXISTS (
         SELECT 1 FROM users WHERE users.id = user_usage.user_id
       )`
    );
    console.log(`Cleaned up ${rowCount || 0} orphaned usage records`);
  } catch (error) {
    console.error("Error in orphaned records cleanup job:", error);
  }
}
var monthlyResetJob = new CronJob(
  "0 0 1 * *",
  resetMonthlyUsage,
  null,
  false,
  "UTC"
  // Explicitly set timezone to UTC
);
var cleanupJob = new CronJob(
  "0 1 1 * *",
  cleanupOrphanedRecords,
  null,
  false,
  "UTC"
  // Explicitly set timezone to UTC
);
function startCronJobs() {
  monthlyResetJob.start();
  cleanupJob.start();
  console.log("Started usage tracking cron jobs");
}

// server/index.ts
var app = express3();
app.use(express3.json());
app.use(express3.urlencoded({ extended: false }));
app.use(cors({
  origin: function(origin, callback) {
    if (!origin) return callback(null, true);
    return callback(null, origin);
  },
  credentials: true,
  // Allow cookies to be sent with requests
  methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
  allowedHeaders: ["Content-Type", "Authorization", "Origin", "X-Requested-With"]
}));
app.use((req, res, next) => {
  console.log(`Request from origin: ${req.headers.origin} to ${req.method} ${req.path}`);
  res.header("Access-Control-Allow-Origin", req.headers.origin || "*");
  res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,PATCH,OPTIONS");
  res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, Content-Length, X-Requested-With, Origin");
  res.header("Access-Control-Allow-Credentials", "true");
  if (req.method === "OPTIONS") {
    res.header("Access-Control-Max-Age", "86400");
    return res.sendStatus(200);
  }
  next();
});
app.use((req, res, next) => {
  const start = Date.now();
  const path3 = req.path;
  let capturedJsonResponse = void 0;
  const originalResJson = res.json;
  res.json = function(bodyJson, ...args) {
    capturedJsonResponse = bodyJson;
    return originalResJson.apply(res, [bodyJson, ...args]);
  };
  res.on("finish", () => {
    const duration = Date.now() - start;
    if (path3.startsWith("/api")) {
      let logLine = `${req.method} ${path3} ${res.statusCode} in ${duration}ms`;
      if (capturedJsonResponse) {
        logLine += ` :: ${JSON.stringify(capturedJsonResponse)}`;
      }
      if (logLine.length > 80) {
        logLine = logLine.slice(0, 79) + "\u2026";
      }
      log(logLine);
    }
  });
  next();
});
async function startServer() {
  try {
    console.log("Using in-memory session store, no PostgreSQL session table needed");
    try {
      console.log("Running schema validation and migrations...");
      const { addMissingUsageColumns: addMissingUsageColumns2 } = await Promise.resolve().then(() => (init_add_missing_usage_columns(), add_missing_usage_columns_exports));
      await addMissingUsageColumns2();
      console.log("Database schema validation complete");
    } catch (migrationError) {
      console.error("Error running migrations:", migrationError);
    }
    const server = await registerRoutes(app);
    startCronJobs();
    app.use((err, _req, res, _next) => {
      const status = err.status || err.statusCode || 500;
      const message = err.message || "Internal Server Error";
      res.status(status).json({ message });
      throw err;
    });
    if (app.get("env") === "development") {
      await setupVite(app, server);
    } else {
      serveStatic(app);
    }
    const port = 5e3;
    server.listen({
      port,
      host: "0.0.0.0",
      reusePort: true
    }, () => {
      log(`serving on port ${port}`);
    });
    return server;
  } catch (error) {
    console.error("Failed to initialize and start server:", error);
    process.exit(1);
  }
}
startServer().catch(console.error);
