// Hatchway CLI - Built with Rollup
import { drizzle } from 'drizzle-orm/node-postgres';
import pg from 'pg';
import { pgTable, timestamp, boolean, text, uuid, index, uniqueIndex, integer, jsonb } from 'drizzle-orm/pg-core';
import { sql } from 'drizzle-orm';
import 'net';
import { readFile } from 'fs/promises';
import { existsSync } from 'fs';
import { join } from 'path';
import * as Sentry from '@sentry/node';

var __defProp = Object.defineProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};

// src/lib/db/schema.ts
var schema_exports = {};
__export(schema_exports, {
  accounts: () => accounts,
  cliAuthSessions: () => cliAuthSessions,
  generationNotes: () => generationNotes,
  generationSessions: () => generationSessions,
  generationTodos: () => generationTodos,
  generationToolCalls: () => generationToolCalls,
  githubConnections: () => githubConnections,
  messages: () => messages,
  portAllocations: () => portAllocations,
  projects: () => projects,
  railwayConnections: () => railwayConnections,
  railwayDeployments: () => railwayDeployments,
  runnerKeys: () => runnerKeys,
  runningProcesses: () => runningProcesses,
  serverOperations: () => serverOperations,
  sessions: () => sessions,
  users: () => users,
  verifications: () => verifications
});
var users = pgTable("users", {
  id: uuid("id").primaryKey().defaultRandom(),
  name: text("name").notNull(),
  email: text("email").notNull().unique(),
  emailVerified: boolean("email_verified").notNull().default(false),
  image: text("image"),
  hasCompletedOnboarding: boolean("has_completed_onboarding").notNull().default(false),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow()
});
var sessions = pgTable("sessions", {
  id: uuid("id").primaryKey().defaultRandom(),
  userId: uuid("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  token: text("token").notNull().unique(),
  expiresAt: timestamp("expires_at").notNull(),
  ipAddress: text("ip_address"),
  userAgent: text("user_agent"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow()
}, (table) => ({
  userIdIdx: index("sessions_user_id_idx").on(table.userId),
  tokenIdx: index("sessions_token_idx").on(table.token)
}));
var accounts = pgTable("accounts", {
  id: uuid("id").primaryKey().defaultRandom(),
  userId: uuid("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  accountId: text("account_id").notNull(),
  providerId: text("provider_id").notNull(),
  // 'credential', 'google', etc.
  accessToken: text("access_token"),
  refreshToken: text("refresh_token"),
  accessTokenExpiresAt: timestamp("access_token_expires_at"),
  refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
  scope: text("scope"),
  idToken: text("id_token"),
  // ID token from OAuth providers
  password: text("password"),
  // Hashed password for credential provider
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow()
}, (table) => ({
  userIdIdx: index("accounts_user_id_idx").on(table.userId),
  providerAccountIdx: uniqueIndex("accounts_provider_account_idx").on(table.providerId, table.accountId)
}));
var verifications = pgTable("verifications", {
  id: uuid("id").primaryKey().defaultRandom(),
  identifier: text("identifier").notNull(),
  // email or other identifier
  value: text("value").notNull(),
  // verification token
  expiresAt: timestamp("expires_at").notNull(),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow()
}, (table) => ({
  identifierIdx: index("verifications_identifier_idx").on(table.identifier)
}));
var runnerKeys = pgTable("runner_keys", {
  id: uuid("id").primaryKey().defaultRandom(),
  userId: uuid("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  name: text("name").notNull(),
  // User-friendly name like "My MacBook"
  keyHash: text("key_hash").notNull(),
  // SHA-256 hash of the full key
  keyPrefix: text("key_prefix").notNull(),
  // First 8 chars for display: "sv_abc123..."
  source: text("source").default("web"),
  // 'web' | 'cli' - how the key was created
  lastUsedAt: timestamp("last_used_at"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  revokedAt: timestamp("revoked_at")
  // Soft delete - null means active
}, (table) => ({
  userIdIdx: index("runner_keys_user_id_idx").on(table.userId),
  keyHashIdx: uniqueIndex("runner_keys_key_hash_idx").on(table.keyHash)
}));
var cliAuthSessions = pgTable("cli_auth_sessions", {
  id: uuid("id").primaryKey().defaultRandom(),
  token: text("token").notNull().unique(),
  // Random token for session identification
  callbackPort: integer("callback_port").notNull(),
  // Port the CLI is listening on
  callbackHost: text("callback_host").default("localhost"),
  // Host for callback
  state: text("state").notNull().default("pending"),
  // 'pending' | 'authenticated' | 'completed' | 'expired'
  userId: uuid("user_id").references(() => users.id, { onDelete: "cascade" }),
  // Set after auth
  runnerKeyId: uuid("runner_key_id").references(() => runnerKeys.id, { onDelete: "cascade" }),
  // Created key
  deviceName: text("device_name"),
  // Auto-detected device name
  expiresAt: timestamp("expires_at").notNull(),
  // Session expiration (short-lived)
  createdAt: timestamp("created_at").notNull().defaultNow(),
  authenticatedAt: timestamp("authenticated_at")
  // When user completed OAuth
}, (table) => ({
  tokenIdx: uniqueIndex("cli_auth_sessions_token_idx").on(table.token),
  expiresAtIdx: index("cli_auth_sessions_expires_at_idx").on(table.expiresAt)
}));
var projects = pgTable("projects", {
  id: uuid("id").primaryKey().defaultRandom(),
  userId: uuid("user_id").references(() => users.id, { onDelete: "set null" }),
  // Owner of the project (nullable for migration/local mode)
  name: text("name").notNull(),
  slug: text("slug").notNull().unique(),
  description: text("description"),
  originalPrompt: text("original_prompt"),
  icon: text("icon").default("Folder"),
  status: text("status").notNull().default("pending"),
  projectType: text("project_type"),
  detectedFramework: text("detected_framework"),
  // Auto-detected framework (astro, next, vite, etc.)
  path: text("path"),
  // Nullable - deprecated, path should be calculated from slug
  runCommand: text("run_command"),
  port: integer("port"),
  devServerPid: integer("dev_server_pid"),
  devServerPort: integer("dev_server_port"),
  devServerStatus: text("dev_server_status").default("stopped"),
  devServerStatusUpdatedAt: timestamp("dev_server_status_updated_at").defaultNow(),
  tunnelUrl: text("tunnel_url"),
  runnerId: text("runner_id"),
  // Runner that created/manages this project
  generationState: text("generation_state"),
  designPreferences: jsonb("design_preferences"),
  // User-specified design constraints (deprecated - use tags)
  tags: jsonb("tags"),
  // Tag-based configuration system
  lastActivityAt: timestamp("last_activity_at").defaultNow(),
  errorMessage: text("error_message"),
  // GitHub integration fields
  githubRepo: text("github_repo"),
  // e.g., "owner/repo-name"
  githubUrl: text("github_url"),
  // Full repository URL
  githubBranch: text("github_branch"),
  // Default branch (e.g., "main")
  githubLastPushedAt: timestamp("github_last_pushed_at"),
  // Last push timestamp
  githubAutoPush: boolean("github_auto_push").default(false),
  // Auto-push after builds
  githubLastSyncAt: timestamp("github_last_sync_at"),
  // Last time we synced repo info
  githubMeta: jsonb("github_meta"),
  // Additional metadata (issues count, recent commits, etc.)
  // NeonDB integration fields
  neondbConnectionString: text("neondb_connection_string"),
  // DATABASE_URL (encrypted/partial)
  neondbClaimUrl: text("neondb_claim_url"),
  // URL to claim the database
  neondbHost: text("neondb_host"),
  // Database host endpoint
  neondbDatabase: text("neondb_database"),
  // Database name
  neondbCreatedAt: timestamp("neondb_created_at"),
  // When database was provisioned
  neondbExpiresAt: timestamp("neondb_expires_at"),
  // When unclaimed DB expires (72 hours)
  // Railway integration fields
  railwayProjectId: text("railway_project_id"),
  // Railway project ID
  railwayServiceId: text("railway_service_id"),
  // Railway service ID
  railwayEnvironmentId: text("railway_environment_id"),
  // Railway environment ID (production)
  railwayDomain: text("railway_domain"),
  // e.g., "myapp-production.up.railway.app"
  railwayDeploymentStatus: text("railway_deployment_status"),
  // 'deploying' | 'success' | 'failed' | 'crashed'
  railwayLastDeployedAt: timestamp("railway_last_deployed_at"),
  // Last successful deployment
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow()
}, (table) => ({
  // Indexes for performance
  userIdIdx: index("projects_user_id_idx").on(table.userId),
  runnerIdIdx: index("projects_runner_id_idx").on(table.runnerId),
  statusIdx: index("projects_status_idx").on(table.status),
  lastActivityIdx: index("projects_last_activity_idx").on(table.lastActivityAt)
}));
var messages = pgTable("messages", {
  id: uuid("id").primaryKey().defaultRandom(),
  projectId: uuid("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
  role: text("role").notNull(),
  content: text("content").notNull(),
  createdAt: timestamp("created_at").notNull().defaultNow()
});
var portAllocations = pgTable("port_allocations", {
  port: integer("port").primaryKey(),
  framework: text("framework").notNull(),
  projectId: uuid("project_id").references(() => projects.id, { onDelete: "set null" }),
  reservedAt: timestamp("reserved_at").defaultNow()
});
var runningProcesses = pgTable("running_processes", {
  projectId: uuid("project_id").primaryKey().notNull().references(() => projects.id, { onDelete: "cascade" }),
  pid: integer("pid").notNull(),
  port: integer("port"),
  command: text("command"),
  runnerId: text("runner_id"),
  // Runner that manages this process
  startedAt: timestamp("started_at").notNull().defaultNow(),
  lastHealthCheck: timestamp("last_health_check"),
  healthCheckFailCount: integer("health_check_fail_count").notNull().default(0)
}, (table) => ({
  // Index for filtering by runner
  runnerIdIdx: index("running_processes_runner_id_idx").on(table.runnerId)
}));
var generationSessions = pgTable("generation_sessions", {
  id: uuid("id").primaryKey().defaultRandom(),
  projectId: uuid("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
  buildId: text("build_id").notNull(),
  operationType: text("operation_type"),
  status: text("status").notNull().default("active"),
  startedAt: timestamp("started_at").notNull().defaultNow(),
  endedAt: timestamp("ended_at"),
  summary: text("summary"),
  rawState: jsonb("raw_state"),
  isAutoFix: boolean("is_auto_fix").default(false),
  // Flag for auto-fix sessions triggered by startup errors
  autoFixError: text("auto_fix_error"),
  // The error message that triggered the auto-fix
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow()
}, (table) => ({
  projectIdIdx: index("generation_sessions_project_id_idx").on(table.projectId),
  buildIdUnique: uniqueIndex("generation_sessions_build_id_unique").on(table.buildId)
}));
var generationTodos = pgTable("generation_todos", {
  id: uuid("id").primaryKey().defaultRandom(),
  sessionId: uuid("session_id").notNull().references(() => generationSessions.id, { onDelete: "cascade" }),
  todoIndex: integer("todo_index").notNull(),
  content: text("content").notNull(),
  activeForm: text("active_form"),
  status: text("status").notNull(),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow()
}, (table) => ({
  sessionIdIdx: index("generation_todos_session_id_idx").on(table.sessionId),
  sessionIndexUnique: uniqueIndex("generation_todos_session_index_unique").on(table.sessionId, table.todoIndex)
}));
var generationToolCalls = pgTable("generation_tool_calls", {
  id: uuid("id").primaryKey().defaultRandom(),
  sessionId: uuid("session_id").notNull().references(() => generationSessions.id, { onDelete: "cascade" }),
  todoIndex: integer("todo_index").notNull(),
  toolCallId: text("tool_call_id").notNull(),
  name: text("name").notNull(),
  input: jsonb("input"),
  output: jsonb("output"),
  state: text("state").notNull(),
  startedAt: timestamp("started_at").notNull().defaultNow(),
  endedAt: timestamp("ended_at"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow()
}, (table) => ({
  sessionIdIdx: index("generation_tool_calls_session_id_idx").on(table.sessionId),
  toolCallUnique: uniqueIndex("generation_tool_calls_call_id_unique").on(table.sessionId, table.toolCallId)
}));
var generationNotes = pgTable("generation_notes", {
  id: uuid("id").primaryKey().defaultRandom(),
  sessionId: uuid("session_id").notNull().references(() => generationSessions.id, { onDelete: "cascade" }),
  todoIndex: integer("todo_index").notNull(),
  textId: text("text_id"),
  kind: text("kind").notNull().default("text"),
  content: text("content").notNull(),
  createdAt: timestamp("created_at").notNull().defaultNow()
}, (table) => ({
  sessionIdIdx: index("generation_notes_session_id_idx").on(table.sessionId),
  textIdUnique: uniqueIndex("generation_notes_text_id_unique").on(table.sessionId, table.textId).where(sql`${table.textId} is not null`)
}));
var railwayConnections = pgTable("railway_connections", {
  id: uuid("id").primaryKey().defaultRandom(),
  userId: uuid("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  // Encrypted OAuth tokens
  accessTokenEncrypted: text("access_token_encrypted").notNull(),
  refreshTokenEncrypted: text("refresh_token_encrypted"),
  accessTokenExpiresAt: timestamp("access_token_expires_at"),
  // Railway user info (from OAuth)
  railwayUserId: text("railway_user_id").notNull(),
  // "sub" claim from OIDC
  railwayEmail: text("railway_email"),
  railwayName: text("railway_name"),
  // Selected workspaces from OAuth consent
  defaultWorkspaceId: text("default_workspace_id"),
  defaultWorkspaceName: text("default_workspace_name"),
  grantedWorkspaces: jsonb("granted_workspaces").$type(),
  // Connection status
  status: text("status").notNull().default("active"),
  // 'active' | 'disconnected' | 'expired'
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow()
}, (table) => ({
  userIdUnique: uniqueIndex("railway_connections_user_id_unique").on(table.userId),
  railwayUserIdIdx: index("railway_connections_railway_user_id_idx").on(table.railwayUserId)
}));
var railwayDeployments = pgTable("railway_deployments", {
  id: uuid("id").primaryKey().defaultRandom(),
  projectId: uuid("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
  // Railway resource IDs
  railwayProjectId: text("railway_project_id").notNull(),
  railwayServiceId: text("railway_service_id").notNull(),
  railwayDeploymentId: text("railway_deployment_id").notNull(),
  railwayEnvironmentId: text("railway_environment_id"),
  // Deployment info
  status: text("status").notNull(),
  // Railway deployment status
  url: text("url"),
  // Deployment URL
  commitSha: text("commit_sha"),
  // Git commit deployed
  // Timestamps
  deployedAt: timestamp("deployed_at").notNull().defaultNow(),
  completedAt: timestamp("completed_at"),
  createdAt: timestamp("created_at").notNull().defaultNow()
}, (table) => ({
  projectIdIdx: index("railway_deployments_project_id_idx").on(table.projectId),
  railwayDeploymentIdIdx: index("railway_deployments_railway_deployment_id_idx").on(table.railwayDeploymentId)
}));
var githubConnections = pgTable("github_connections", {
  id: uuid("id").primaryKey().defaultRandom(),
  userId: uuid("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  // Encrypted OAuth tokens
  accessTokenEncrypted: text("access_token_encrypted").notNull(),
  // GitHub user info (from OAuth)
  githubUserId: text("github_user_id").notNull(),
  // GitHub user ID
  githubUsername: text("github_username").notNull(),
  // GitHub username/login
  githubEmail: text("github_email"),
  githubAvatarUrl: text("github_avatar_url"),
  // OAuth scopes granted
  scopes: text("scopes"),
  // Comma-separated list of scopes
  // Connection status
  status: text("status").notNull().default("active"),
  // 'active' | 'disconnected' | 'expired'
  createdAt: timestamp("created_at").notNull().defaultNow(),
  updatedAt: timestamp("updated_at").notNull().defaultNow()
}, (table) => ({
  userIdUnique: uniqueIndex("github_connections_user_id_unique").on(table.userId),
  githubUserIdIdx: index("github_connections_github_user_id_idx").on(table.githubUserId)
}));
var serverOperations = pgTable("server_operations", {
  id: uuid("id").primaryKey().defaultRandom(),
  projectId: uuid("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
  operation: text("operation").notNull(),
  // 'start', 'stop', 'restart'
  status: text("status").notNull().default("pending"),
  // 'pending', 'sent', 'ack', 'completed', 'failed', 'timeout'
  runnerId: text("runner_id"),
  port: integer("port"),
  pid: integer("pid"),
  error: text("error"),
  failureReason: text("failure_reason"),
  // 'port_in_use', 'health_check_timeout', 'immediate_crash', etc.
  retryCount: integer("retry_count").notNull().default(0),
  metadata: jsonb("metadata"),
  createdAt: timestamp("created_at").notNull().defaultNow(),
  sentAt: timestamp("sent_at"),
  ackAt: timestamp("ack_at"),
  completedAt: timestamp("completed_at")
}, (table) => ({
  projectIdIdx: index("server_operations_project_id_idx").on(table.projectId),
  statusIdx: index("server_operations_status_idx").on(table.status),
  createdAtIdx: index("server_operations_created_at_idx").on(table.createdAt)
}));

// src/lib/db/client.ts
var { Pool } = pg;
function createPostgresClient() {
  const connectionString = process.env.DATABASE_URL;
  if (!connectionString) {
    throw new Error(
      'DATABASE_URL is not set. Please configure your database connection:\n  - Run "hatchway init" to set up a Neon database\n  - Or set DATABASE_URL environment variable to your PostgreSQL connection string'
    );
  }
  const pool = new Pool({
    connectionString,
    ssl: process.env.PGSSLMODE === "disable" ? false : { rejectUnauthorized: false }
  });
  const client = drizzle(pool, { schema: schema_exports });
  return client;
}
new Proxy({}, {
  get(_target, prop) {
    if (!global.__db) {
      global.__db = createPostgresClient();
    }
    return global.__db[prop];
  }
});
var BuildLogger = class {
  buildId = null;
  projectId = null;
  /**
   * Set correlation IDs for the current build
   * Call this at the start of each build to enable correlation tracking
   */
  setBuildContext(buildId, projectId) {
    this.buildId = buildId;
    this.projectId = projectId;
    this.log("debug", "runner", `Build context set: ${buildId} / ${projectId}`);
  }
  /**
   * Clear correlation IDs after build completes
   */
  clearBuildContext() {
    this.log("debug", "runner", "Build context cleared");
    this.buildId = null;
    this.projectId = null;
  }
  /**
   * Core logging method - creates structured log entries
   * Public for custom logging needs
   */
  log(level, context, message, data) {
    if (process.env.SILENT_MODE === "1") {
      return;
    }
    if (level === "info" || level === "debug") {
      if (process.env.DEBUG_BUILD === "0") {
        return;
      }
    }
    ({
      timestamp: (/* @__PURE__ */ new Date()).toISOString(),
      buildId: this.buildId ?? void 0,
      projectId: this.projectId ?? void 0});
    const prefix = `[${context}]`;
    const icon = {
      debug: "\u{1F50D}",
      info: "\u{1F4CB}",
      warn: "\u26A0\uFE0F ",
      error: "\u274C"
    }[level];
    const logFn = level === "error" ? console.error : level === "warn" ? console.warn : console.log;
    if (data && Object.keys(data).length > 0) {
      logFn(`${icon} ${prefix} ${message}`, data);
    } else {
      logFn(`${icon} ${prefix} ${message}`);
    }
    if (typeof process !== "undefined" && process.env.NODE_ENV !== "test") {
      try {
        if (level === "warn" || level === "error") {
          Sentry.addBreadcrumb({
            category: `build-logger.${context}`,
            message,
            level: level === "error" ? "error" : "warning",
            data: {
              ...data,
              buildId: this.buildId,
              projectId: this.projectId
            }
          });
        }
      } catch {
      }
    }
  }
  /**
   * Orchestrator-specific logging methods
   */
  orchestrator = {
    newProject: (operationType) => this.log("info", "orchestrator", `NEW PROJECT (operationType: ${operationType})`),
    existingProject: (operationType) => this.log("info", "orchestrator", `EXISTING PROJECT (operationType: ${operationType})`),
    templateProvided: (templateName, templateId, framework) => this.log("info", "orchestrator", `Frontend provided template: ${templateName}`, {
      templateId,
      framework
    }),
    templateSelecting: (method) => this.log("info", "orchestrator", `Template selection: ${method}`),
    templateSelected: (templateName, templateId) => this.log("info", "orchestrator", `Selected template: ${templateName}`, { templateId }),
    templateDownloading: (templateName, repository, target) => this.log("info", "orchestrator", `Downloading template: ${templateName}`, {
      repository,
      target
    }),
    templateDownloaded: (templateName, path, fileTreeSize) => this.log("info", "orchestrator", `Template downloaded: ${templateName}`, {
      path,
      fileTreeSize
    }),
    catalogPrepared: (catalogSize) => this.log("info", "orchestrator", `Template catalog prepared (${catalogSize} chars)`, {
      catalogSize
    }),
    systemPromptGenerated: (size) => this.log("info", "orchestrator", `System prompt generated (${size} chars)`, { size }),
    orchestrationComplete: (data) => this.log("info", "orchestrator", "Orchestration complete", data),
    error: (message, error) => this.log("error", "orchestrator", message, {
      error: error instanceof Error ? error.message : String(error)
    })
  };
  /**
   * Message transformer-specific logging methods
   */
  transformer = {
    todoListFound: () => this.log("debug", "transformer", "Found Codex task list, parsing..."),
    todoListParsed: (todoCount, completed, inProgress, pending) => this.log("info", "transformer", `Parsed ${todoCount} todos`, {
      completed,
      inProgress,
      pending
    }),
    todoListInvalidFormat: (expected, got) => this.log("error", "transformer", "Invalid todo format from Codex", {
      expected,
      got: JSON.stringify(got).substring(0, 200)
    }),
    todoListParseError: (error, rawJson) => this.log("error", "transformer", "Failed to parse Codex todolist", {
      error: String(error),
      rawJson: rawJson.substring(0, 300)
    }),
    todoListRemoved: () => this.log("debug", "transformer", "Removed task list from chat text"),
    toolStarted: (toolName, toolId) => this.log("debug", "transformer", `Tool started: ${toolName}`, { toolName, toolId }),
    toolCompleted: (toolName, toolId) => this.log("debug", "transformer", `Tool completed: ${toolName}`, { toolName, toolId }),
    pathViolationWarning: (toolName, path, workspace) => this.log("warn", "transformer", `Path outside workspace: ${path}`, {
      toolName,
      path,
      workspace
    }),
    desktopPathDetected: (path) => this.log("error", "transformer", `DESKTOP PATH DETECTED - Likely hallucinated: ${path}`, { path })
  };
  /**
   * Codex query-specific logging methods
   */
  codexQuery = {
    promptBuilding: (workingDirectory, systemPromptSize, userPromptSize) => this.log("info", "codex-query", "Building Codex prompt", {
      workingDirectory,
      systemPromptSize,
      userPromptSize
    }),
    threadStarting: () => this.log("info", "codex-query", "Starting Codex thread (multi-turn)"),
    turnStarted: (turnNumber, maxTurns, promptSize) => this.log("info", "codex-query", `\u2550\u2550\u2550 Turn ${turnNumber}/${maxTurns} \u2550\u2550\u2550`, {
      turnNumber,
      maxTurns,
      promptSize
    }),
    taskListExtracted: () => this.log("info", "codex-query", "Task list extracted and updated"),
    taskListStatus: (completed, inProgress, pending, total) => this.log("info", "codex-query", `Tasks: ${completed} completed | ${inProgress} in_progress | ${pending} pending (total: ${total})`, {
      completed,
      inProgress,
      pending,
      total
    }),
    taskListTask: (index2, content, status, icon) => this.log("debug", "codex-query", `  ${icon} ${index2 + 1}. ${content}`, { status }),
    taskListParseError: (error, rawContent) => this.log("error", "codex-query", "PARSE ERROR: Could not parse task list JSON", {
      error: String(error),
      rawContent: rawContent.substring(0, 200)
    }),
    taskListMissing: (turnNumber) => this.log("warn", "codex-query", `WARNING: No <start-todolist> tags found in Turn ${turnNumber}`, {
      turnNumber
    }),
    turnComplete: (turnNumber, hadToolCalls, messageLength) => this.log("info", "codex-query", `Turn ${turnNumber} complete`, {
      hadToolCalls,
      messageLength
    }),
    tasksComplete: (completed, total) => this.log("info", "codex-query", `Task status: ${completed}/${total} completed`, {
      completed,
      total
    }),
    allComplete: () => this.log("info", "codex-query", "\u2705 All MVP tasks complete!"),
    allTasksComplete: () => this.log("info", "codex-query", "\u2705 All MVP tasks complete!"),
    taskCompleteDetected: () => this.log("info", "codex-query", "\u2705 Task complete (detected completion signal)"),
    continuePrompting: (reason) => this.log("warn", "codex-query", `No tools used but not done - ${reason}`),
    continuing: () => this.log("info", "codex-query", "\u23ED\uFE0F  Continuing to next turn (had tool calls)"),
    loopExited: (turnCount, maxTurns) => this.log("info", "codex-query", `EXITED WHILE LOOP after ${turnCount} turns`, {
      turnCount,
      maxTurns
    }),
    sessionComplete: (turnCount) => this.log("info", "codex-query", `Session complete after ${turnCount} turns`, { turnCount }),
    error: (message, error) => this.log("error", "codex-query", message, {
      error: error instanceof Error ? error.message : String(error)
    })
  };
  /**
   * Claude query-specific logging methods
   */
  claudeQuery = {
    queryStarted: (model, cwd, maxTurns) => this.log("info", "claude-query", `Starting Claude query (${model})`, {
      cwd,
      maxTurns
    }),
    error: (message, error) => this.log("error", "claude-query", message, {
      error: error instanceof Error ? error.message : String(error)
    })
  };
  /**
   * Runner-specific logging methods
   */
  runner = {
    workspaceRoot: (path) => this.log("info", "runner", `Workspace root: ${path}`, { path }),
    commandReceived: (commandType, projectId) => this.log("info", "runner", `Received command: ${commandType}`, { commandType, projectId }),
    buildOperation: (operationType, projectSlug, agentId) => this.log("info", "runner", `Build operation: ${operationType}`, {
      operationType,
      projectSlug,
      agentId
    }),
    templateProvided: (templateId) => this.log("info", "runner", `Template provided by frontend: ${templateId}`, { templateId }),
    buildStreamCreated: () => this.log("info", "runner", "Build stream created, starting to process chunks..."),
    firstChunkReceived: (agentLabel) => this.log("info", "runner", `First chunk received from ${agentLabel}`, { agentLabel }),
    streamEnded: (chunkCount) => this.log("info", "runner", `Stream ended after ${chunkCount} chunks`, { chunkCount }),
    buildCompleted: (projectId) => this.log("info", "runner", `Build completed successfully`, { projectId }),
    buildFailed: (error) => this.log("error", "runner", `Build failed: ${error}`, { error }),
    portDetected: (port) => this.log("info", "runner", `Port detected: ${port}`, { port }),
    tunnelCreated: (port, tunnelUrl) => this.log("info", "runner", `Tunnel created: ${tunnelUrl} \u2192 localhost:${port}`, {
      port,
      tunnelUrl
    }),
    error: (message, error, context) => this.log("error", "runner", message, {
      error: error instanceof Error ? error.message : String(error),
      stack: error instanceof Error ? error.stack : void 0,
      ...context
    })
  };
  /**
   * Build stream-specific logging (tool calls, text, etc.)
   */
  build = {
    agentText: (agentLabel, text2) => {
      const truncated = text2.length > 200 ? text2.slice(0, 200) + "..." : text2;
      this.log("debug", "build", `${agentLabel}: ${truncated}`, {
        agentLabel,
        textLength: text2.length
      });
    },
    agentThinking: (thinking) => {
      const truncated = thinking.length > 300 ? thinking.slice(0, 300) + "..." : thinking;
      this.log("debug", "build", `Thinking: ${truncated}`, {
        thinkingLength: thinking.length
      });
    },
    toolCalled: (toolName, toolId, inputSize) => this.log("info", "build", `Tool called: ${toolName} (${toolId})`, {
      toolName,
      toolId,
      inputSize
    }),
    toolResult: (toolId, outputSize, isError) => this.log(isError ? "error" : "info", "build", `Tool result (${toolId})`, {
      toolId,
      outputSize,
      isError
    }),
    runCommandDetected: (runCommand) => this.log("info", "build", `Detected runCommand: ${runCommand}`, { runCommand })
  };
  /**
   * WebSocket-specific logging methods
   */
  websocket = {
    serverCreated: (instanceId) => this.log("info", "websocket", `WebSocket server instance created`, { instanceId }),
    serverInitialized: (path, runnerPath) => this.log("info", "websocket", `Server initialized`, { path, runnerPath }),
    clientConnected: (clientId, projectId, sessionId) => this.log("info", "websocket", `Client connected: ${clientId}`, { clientId, projectId, sessionId }),
    clientDisconnected: (clientId) => this.log("info", "websocket", `Client disconnected: ${clientId}`, { clientId }),
    clientSubscribed: (clientId, projectId) => this.log("info", "websocket", `Client subscribed to project: ${projectId}`, { clientId, projectId }),
    clientTimeout: (clientId) => this.log("warn", "websocket", `Client timeout: ${clientId}`, { clientId }),
    runnerConnected: (runnerId) => this.log("info", "websocket", `Runner connected: ${runnerId}`, { runnerId }),
    runnerDisconnected: (runnerId, code) => this.log("info", "websocket", `Runner disconnected: ${runnerId}`, { runnerId, code }),
    runnerNotConnected: (runnerId, commandType) => this.log("warn", "websocket", `Cannot send command to runner ${runnerId}: not connected`, {
      runnerId,
      commandType
    }),
    runnerAuthRejected: () => this.log("warn", "websocket", `Runner connection rejected: invalid auth`),
    runnerAuthMissing: () => this.log("error", "websocket", `RUNNER_SHARED_SECRET is not configured`),
    runnerStaleRemoved: (runnerId) => this.log("info", "websocket", `Removing stale runner connection: ${runnerId}`, { runnerId }),
    commandSent: (runnerId, commandType, traceAttached) => this.log("debug", "websocket", `Sent command to runner: ${commandType}`, {
      runnerId,
      commandType,
      traceAttached
    }),
    eventReceived: (runnerId, eventType) => this.log("debug", "websocket", `Received event from runner: ${eventType}`, {
      runnerId,
      eventType
    }),
    broadcastToolCall: (toolName, toolState, subscriberCount) => this.log("info", "websocket", `Broadcasting planning tool: ${toolName} (state=${toolState})`, {
      toolName,
      toolState,
      subscriberCount
    }),
    broadcastBuildComplete: (projectId, sessionId, subscriberCount) => this.log("info", "websocket", `Broadcasting build-complete`, {
      projectId,
      sessionId,
      subscriberCount
    }),
    unknownUpgradePath: (pathname) => this.log("warn", "websocket", `Unknown upgrade path: ${pathname}`, { pathname }),
    shutdown: () => this.log("info", "websocket", `Shutting down server...`),
    shutdownComplete: () => this.log("info", "websocket", `Server shut down`),
    error: (message, error, context) => this.log("error", "websocket", message, {
      error: error instanceof Error ? error.message : String(error),
      stack: error instanceof Error ? error.stack : void 0,
      ...context
    })
  };
  /**
   * Port allocator-specific logging methods
   */
  portAllocator = {
    portAllocated: (port, projectId) => this.log("info", "port-allocator", `Port allocated: ${port}`, { port, projectId }),
    portReleased: (port, projectId) => this.log("info", "port-allocator", `Port released: ${port}`, { port, projectId }),
    portInUse: (port) => this.log("warn", "port-allocator", `Port ${port} is already in use`, { port }),
    portRangeExhausted: (minPort, maxPort) => this.log("error", "port-allocator", `No available ports in range ${minPort}-${maxPort}`, {
      minPort,
      maxPort
    }),
    portConflict: (port, projectId, existingProjectId) => this.log("warn", "port-allocator", `Port ${port} conflict detected`, {
      port,
      projectId,
      existingProjectId
    }),
    allocationsCleared: (count) => this.log("info", "port-allocator", `Cleared ${count} port allocations`, { count }),
    error: (message, error, context) => this.log("error", "port-allocator", message, {
      error: error instanceof Error ? error.message : String(error),
      ...context
    })
  };
  /**
   * Process manager-specific logging methods
   */
  processManager = {
    processStarting: (projectId, command, cwd) => this.log("info", "process-manager", `Starting process: ${command}`, {
      projectId,
      command,
      cwd
    }),
    processStarted: (projectId, pid) => this.log("info", "process-manager", `Process started`, { projectId, pid }),
    processOutput: (projectId, output) => this.log("debug", "process-manager", `Process output: ${output.substring(0, 100)}`, {
      projectId,
      outputLength: output.length
    }),
    processError: (projectId, error) => this.log("error", "process-manager", `Process error: ${error}`, { projectId, error }),
    processExited: (projectId, code, signal) => this.log("info", "process-manager", `Process exited`, { projectId, code, signal }),
    processStopped: (projectId) => this.log("info", "process-manager", `Process stopped`, { projectId }),
    processNotFound: (projectId) => this.log("warn", "process-manager", `Process not found for project: ${projectId}`, { projectId }),
    processKilled: (projectId, signal) => this.log("info", "process-manager", `Process killed with signal: ${signal}`, {
      projectId,
      signal
    }),
    processCleanup: (projectId) => this.log("info", "process-manager", `Cleaning up process`, { projectId }),
    processListRetrieved: (count) => this.log("debug", "process-manager", `Retrieved ${count} running processes`, { count }),
    error: (message, error, context) => this.log("error", "process-manager", message, {
      error: error instanceof Error ? error.message : String(error),
      stack: error instanceof Error ? error.stack : void 0,
      ...context
    })
  };
  /**
   * Build events-specific logging methods
   */
  buildEvents = {
    eventReceived: (eventType, projectId, sessionId) => this.log("info", "build-events", `Received event: ${eventType}`, {
      eventType,
      projectId,
      sessionId
    }),
    eventProcessed: (eventType, projectId) => this.log("debug", "build-events", `Processed event: ${eventType}`, { eventType, projectId }),
    buildStarted: (projectId, sessionId) => this.log("info", "build-events", `Build started`, { projectId, sessionId }),
    buildCompleted: (projectId, sessionId, success) => this.log("info", "build-events", `Build ${success ? "completed" : "failed"}`, {
      projectId,
      sessionId,
      success
    }),
    portDetected: (projectId, port) => this.log("info", "build-events", `Port detected: ${port}`, { projectId, port }),
    devServerStarted: (projectId, port, url) => this.log("info", "build-events", `Dev server started: ${url}`, { projectId, port, url }),
    devServerError: (projectId, error) => this.log("error", "build-events", `Dev server error: ${error}`, { projectId, error }),
    toolCallReceived: (toolName, toolId) => this.log("debug", "build-events", `Tool call: ${toolName}`, { toolName, toolId }),
    logChunkReceived: (projectId, chunkSize) => this.log("debug", "build-events", `Log chunk received`, { projectId, chunkSize }),
    invalidEvent: (reason) => this.log("warn", "build-events", `Invalid event: ${reason}`, { reason }),
    error: (message, error, context) => this.log("error", "build-events", message, {
      error: error instanceof Error ? error.message : String(error),
      stack: error instanceof Error ? error.stack : void 0,
      ...context
    })
  };
};
var buildLogger = new BuildLogger();
async function detectFrameworkFromFilesystem(projectPath) {
  try {
    let cachedPkg = null;
    const loadPackageJson = async () => {
      if (cachedPkg) return cachedPkg;
      const pkgPath = join(projectPath, "package.json");
      if (!existsSync(pkgPath)) {
        cachedPkg = null;
        return cachedPkg;
      }
      const pkgContent = await readFile(pkgPath, "utf-8");
      const pkg2 = JSON.parse(pkgContent);
      cachedPkg = {
        deps: { ...pkg2.dependencies ?? {}, ...pkg2.peerDependencies ?? {} },
        devDeps: pkg2.devDependencies ?? {},
        devScript: pkg2.scripts?.dev?.toLowerCase() ?? ""
      };
      return cachedPkg;
    };
    const hasTanStackDependency = async () => {
      const pkg2 = await loadPackageJson();
      if (!pkg2) return false;
      const combined = { ...pkg2.deps, ...pkg2.devDeps };
      if (combined["@tanstack/react-start"]) return true;
      if (pkg2.devScript.includes("tanstack")) return true;
      return false;
    };
    if (existsSync(join(projectPath, "astro.config.mjs")) || existsSync(join(projectPath, "astro.config.ts")) || existsSync(join(projectPath, "astro.config.js"))) {
      return "astro";
    }
    if (existsSync(join(projectPath, "next.config.ts")) || existsSync(join(projectPath, "next.config.js")) || existsSync(join(projectPath, "next.config.mjs"))) {
      return "next";
    }
    if (existsSync(join(projectPath, "vite.config.ts")) || existsSync(join(projectPath, "vite.config.js"))) {
      if (await hasTanStackDependency()) {
        return "tanstack";
      }
      return "vite";
    }
    const pkg = await loadPackageJson();
    if (pkg) {
      const allDeps = { ...pkg.deps, ...pkg.devDeps };
      if (allDeps["astro"]) return "astro";
      if (allDeps["@tanstack/react-start"]) return "tanstack";
      if (allDeps["next"]) return "next";
      if (allDeps["vite"]) return "vite";
      if (pkg.devScript.includes("tanstack")) return "tanstack";
      if (pkg.devScript.includes("astro")) return "astro";
      if (pkg.devScript.includes("next")) return "next";
      if (pkg.devScript.includes("vite")) return "vite";
    }
  } catch (error) {
    buildLogger.portAllocator.error("Failed to detect framework from filesystem", error);
  }
  return null;
}

export { detectFrameworkFromFilesystem };
//# sourceMappingURL=port-allocator-BENntRMG.js.map
