import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { v4 as uuidv4 } from "uuid";
import { logger } from "../monitoring/logger.js";
import { trace } from "../trace/index.js";
import {
  FrameError,
  SystemError,
  ErrorCode
} from "../errors/index.js";
import { FrameQueryMode } from "../session/index.js";
const MAX_FRAME_DEPTH = 100;
const DEFAULT_MAX_DEPTH = 100;
import { FrameDatabase } from "./frame-database.js";
import { FrameStack } from "./frame-stack.js";
import { FrameDigestGenerator } from "./frame-digest.js";
class RefactoredFrameManager {
  frameDb;
  frameStack;
  digestGenerator;
  currentRunId;
  sessionId;
  projectId;
  queryMode = FrameQueryMode.PROJECT_ACTIVE;
  config;
  maxFrameDepth = DEFAULT_MAX_DEPTH;
  constructor(db, projectId, config) {
    this.projectId = projectId;
    this.config = {
      projectId,
      runId: config?.runId || uuidv4(),
      sessionId: config?.sessionId || uuidv4(),
      maxStackDepth: config?.maxStackDepth || 50
    };
    this.maxFrameDepth = config?.maxStackDepth || DEFAULT_MAX_DEPTH;
    this.currentRunId = this.config.runId;
    this.sessionId = this.config.sessionId;
    this.frameDb = new FrameDatabase(db);
    this.frameStack = new FrameStack(
      this.frameDb,
      projectId,
      this.currentRunId
    );
    this.digestGenerator = new FrameDigestGenerator(this.frameDb);
    this.frameDb.initSchema();
    logger.info("RefactoredFrameManager initialized", {
      projectId: this.projectId,
      runId: this.currentRunId,
      sessionId: this.sessionId
    });
  }
  /**
   * Initialize the frame manager
   */
  async initialize() {
    try {
      await this.frameStack.initialize();
      logger.info("Frame manager initialization completed", {
        stackDepth: this.frameStack.getDepth()
      });
    } catch (error) {
      throw new SystemError(
        "Failed to initialize frame manager",
        ErrorCode.SYSTEM_INIT_FAILED,
        { projectId: this.projectId },
        error instanceof Error ? error : void 0
      );
    }
  }
  createFrame(typeOrOptions, name, inputs, parentFrameId) {
    return trace.traceSync(
      "function",
      "FrameManager.createFrame",
      { typeOrOptions, name },
      () => this._createFrame(typeOrOptions, name, inputs, parentFrameId)
    );
  }
  _createFrame(typeOrOptions, name, inputs, parentFrameId) {
    let frameOptions;
    if (typeof typeOrOptions === "string") {
      frameOptions = {
        type: typeOrOptions,
        name,
        inputs: inputs || {},
        parentFrameId
      };
    } else {
      frameOptions = typeOrOptions;
    }
    if (!frameOptions.name || frameOptions.name.trim().length === 0) {
      throw new FrameError(
        "Frame name is required",
        ErrorCode.FRAME_INVALID_INPUT,
        { frameOptions }
      );
    }
    if (this.frameStack.getDepth() >= this.config.maxStackDepth) {
      throw new FrameError(
        `Maximum stack depth reached: ${this.config.maxStackDepth}`,
        ErrorCode.FRAME_STACK_OVERFLOW,
        { currentDepth: this.frameStack.getDepth() }
      );
    }
    const resolvedParentId = frameOptions.parentFrameId || this.frameStack.getCurrentFrameId();
    let depth = 0;
    if (resolvedParentId) {
      const parentFrame = this.frameDb.getFrame(resolvedParentId);
      depth = parentFrame ? parentFrame.depth + 1 : 0;
    }
    if (depth > this.maxFrameDepth) {
      throw new FrameError(
        `Maximum frame depth exceeded: ${depth} > ${this.maxFrameDepth}`,
        ErrorCode.FRAME_STACK_OVERFLOW,
        {
          currentDepth: depth,
          maxDepth: this.maxFrameDepth,
          frameName: frameOptions.name,
          parentFrameId: resolvedParentId
        }
      );
    }
    if (resolvedParentId) {
      const cycle = this.detectCycle(uuidv4(), resolvedParentId);
      if (cycle) {
        throw new FrameError(
          `Circular reference detected in frame hierarchy`,
          ErrorCode.FRAME_CYCLE_DETECTED,
          {
            parentFrameId: resolvedParentId,
            cycle,
            frameName: frameOptions.name
          }
        );
      }
    }
    const frameId = uuidv4();
    const frame = {
      frame_id: frameId,
      run_id: this.currentRunId,
      project_id: this.projectId,
      parent_frame_id: resolvedParentId,
      depth,
      type: frameOptions.type,
      name: frameOptions.name,
      state: "active",
      inputs: frameOptions.inputs || {},
      outputs: {},
      digest_json: {}
    };
    const createdFrame = this.frameDb.insertFrame(frame);
    this.frameStack.pushFrame(frameId);
    logger.info("Created frame", {
      frameId,
      name: frameOptions.name,
      type: frameOptions.type,
      parentFrameId: resolvedParentId,
      stackDepth: this.frameStack.getDepth()
    });
    return frameId;
  }
  /**
   * Close a frame and generate digest
   */
  closeFrame(frameId, outputs) {
    trace.traceSync(
      "function",
      "FrameManager.closeFrame",
      { frameId, outputs },
      () => this._closeFrame(frameId, outputs)
    );
  }
  _closeFrame(frameId, outputs) {
    const targetFrameId = frameId || this.frameStack.getCurrentFrameId();
    if (!targetFrameId) {
      throw new FrameError(
        "No active frame to close",
        ErrorCode.FRAME_INVALID_STATE,
        {
          operation: "closeFrame",
          stackDepth: this.frameStack.getDepth()
        }
      );
    }
    const frame = this.frameDb.getFrame(targetFrameId);
    if (!frame) {
      throw new FrameError(
        `Frame not found: ${targetFrameId}`,
        ErrorCode.FRAME_NOT_FOUND,
        {
          frameId: targetFrameId,
          operation: "closeFrame",
          runId: this.currentRunId
        }
      );
    }
    if (frame.state === "closed") {
      logger.warn("Attempted to close already closed frame", {
        frameId: targetFrameId
      });
      return;
    }
    const digest = this.digestGenerator.generateDigest(targetFrameId);
    const finalOutputs = { ...outputs, ...digest.structured };
    this.frameDb.updateFrame(targetFrameId, {
      state: "closed",
      outputs: finalOutputs,
      digest_text: digest.text,
      digest_json: digest.structured,
      closed_at: Math.floor(Date.now() / 1e3)
    });
    this.frameStack.popFrame(targetFrameId);
    this.closeChildFrames(targetFrameId);
    logger.info("Closed frame", {
      frameId: targetFrameId,
      name: frame.name,
      duration: Math.floor(Date.now() / 1e3) - frame.created_at,
      digestLength: digest.text.length,
      stackDepth: this.frameStack.getDepth()
    });
  }
  /**
   * Add an event to the current frame
   */
  addEvent(eventType, payload, frameId) {
    return trace.traceSync(
      "function",
      "FrameManager.addEvent",
      { eventType, frameId },
      () => this._addEvent(eventType, payload, frameId)
    );
  }
  _addEvent(eventType, payload, frameId) {
    const targetFrameId = frameId || this.frameStack.getCurrentFrameId();
    if (!targetFrameId) {
      throw new FrameError(
        "No active frame for event",
        ErrorCode.FRAME_INVALID_STATE,
        {
          eventType,
          operation: "addEvent"
        }
      );
    }
    const eventId = uuidv4();
    const sequence = this.frameDb.getNextEventSequence(targetFrameId);
    const event = {
      event_id: eventId,
      frame_id: targetFrameId,
      run_id: this.currentRunId,
      seq: sequence,
      event_type: eventType,
      payload
    };
    const createdEvent = this.frameDb.insertEvent(event);
    logger.debug("Added event", {
      eventId,
      frameId: targetFrameId,
      eventType,
      sequence
    });
    return eventId;
  }
  /**
   * Add an anchor (important fact) to current frame
   */
  addAnchor(type, text, priority = 5, metadata = {}, frameId) {
    return trace.traceSync(
      "function",
      "FrameManager.addAnchor",
      { type, frameId },
      () => this._addAnchor(type, text, priority, metadata, frameId)
    );
  }
  _addAnchor(type, text, priority, metadata, frameId) {
    const targetFrameId = frameId || this.frameStack.getCurrentFrameId();
    if (!targetFrameId) {
      throw new FrameError(
        "No active frame for anchor",
        ErrorCode.FRAME_INVALID_STATE,
        {
          anchorType: type,
          operation: "addAnchor"
        }
      );
    }
    const anchorId = uuidv4();
    const anchor = {
      anchor_id: anchorId,
      frame_id: targetFrameId,
      type,
      text,
      priority,
      metadata
    };
    const createdAnchor = this.frameDb.insertAnchor(anchor);
    logger.debug("Added anchor", {
      anchorId,
      frameId: targetFrameId,
      type,
      priority
    });
    return anchorId;
  }
  /**
   * Get hot stack context
   */
  getHotStackContext(maxEvents = 20) {
    return this.frameStack.getHotStackContext(maxEvents);
  }
  /**
   * Get active frame path (root to current)
   */
  getActiveFramePath() {
    return this.frameStack.getStackFrames();
  }
  /**
   * Get current frame ID
   */
  getCurrentFrameId() {
    return this.frameStack.getCurrentFrameId();
  }
  /**
   * Get stack depth
   */
  getStackDepth() {
    return this.frameStack.getDepth();
  }
  /**
   * Get frame by ID
   */
  getFrame(frameId) {
    return this.frameDb.getFrame(frameId);
  }
  /**
   * Get frame events
   */
  getFrameEvents(frameId, limit) {
    return this.frameDb.getFrameEvents(frameId, limit);
  }
  /**
   * Get frame anchors
   */
  getFrameAnchors(frameId) {
    return this.frameDb.getFrameAnchors(frameId);
  }
  /**
   * Generate digest for a frame
   */
  generateDigest(frameId) {
    return this.digestGenerator.generateDigest(frameId);
  }
  /**
   * Validate stack consistency
   */
  validateStack() {
    return this.frameStack.validateStack();
  }
  /**
   * Get database statistics
   */
  getStatistics() {
    return this.frameDb.getStatistics();
  }
  /**
   * Close all child frames recursively
   */
  closeChildFrames(parentFrameId) {
    try {
      const activeFrames = this.frameDb.getFramesByProject(
        this.projectId,
        "active"
      );
      const childFrames = activeFrames.filter(
        (f) => f.parent_frame_id === parentFrameId
      );
      for (const childFrame of childFrames) {
        if (this.frameStack.isFrameActive(childFrame.frame_id)) {
          this.closeFrame(childFrame.frame_id);
        }
      }
    } catch (error) {
      logger.warn("Failed to close child frames", { parentFrameId, error });
    }
  }
  /**
   * Extract active artifacts from frame events
   */
  getActiveArtifacts(frameId) {
    const events = this.frameDb.getFrameEvents(frameId);
    const artifacts = [];
    for (const event of events) {
      if (event.event_type === "artifact" && event.payload.path) {
        artifacts.push(event.payload.path);
      }
    }
    return [...new Set(artifacts)];
  }
  /**
   * Extract constraints from frame inputs
   */
  extractConstraints(inputs) {
    const constraints = [];
    if (inputs.constraints && Array.isArray(inputs.constraints)) {
      constraints.push(...inputs.constraints);
    }
    if (inputs.requirements && Array.isArray(inputs.requirements)) {
      constraints.push(...inputs.requirements);
    }
    if (inputs.limitations && Array.isArray(inputs.limitations)) {
      constraints.push(...inputs.limitations);
    }
    return constraints;
  }
  /**
   * Detect if setting a parent frame would create a cycle in the frame hierarchy.
   * Returns the cycle path if detected, or null if no cycle.
   * @param childFrameId - The frame that would be the child
   * @param parentFrameId - The proposed parent frame
   * @returns Array of frame IDs forming the cycle, or null if no cycle
   */
  detectCycle(childFrameId, parentFrameId) {
    const visited = /* @__PURE__ */ new Set();
    const path = [];
    let currentId = parentFrameId;
    while (currentId) {
      if (visited.has(currentId)) {
        const cycleStart = path.indexOf(currentId);
        return path.slice(cycleStart).concat(currentId);
      }
      if (currentId === childFrameId) {
        return path.concat([currentId, childFrameId]);
      }
      visited.add(currentId);
      path.push(currentId);
      const frame = this.frameDb.getFrame(currentId);
      if (!frame) {
        break;
      }
      currentId = frame.parent_frame_id;
      if (path.length > this.maxFrameDepth) {
        throw new FrameError(
          `Frame hierarchy traversal exceeded maximum depth during cycle detection`,
          ErrorCode.FRAME_STACK_OVERFLOW,
          {
            depth: path.length,
            maxDepth: this.maxFrameDepth,
            path
          }
        );
      }
    }
    return null;
  }
  /**
   * Update parent frame of an existing frame (with cycle detection)
   * @param frameId - The frame to update
   * @param newParentFrameId - The new parent frame ID (null to make it a root frame)
   */
  updateParentFrame(frameId, newParentFrameId) {
    const frame = this.frameDb.getFrame(frameId);
    if (!frame) {
      throw new FrameError(
        `Frame not found: ${frameId}`,
        ErrorCode.FRAME_NOT_FOUND,
        { frameId }
      );
    }
    if (newParentFrameId) {
      const cycle = this.detectCycle(frameId, newParentFrameId);
      if (cycle) {
        throw new FrameError(
          `Cannot set parent: would create circular reference`,
          ErrorCode.FRAME_CYCLE_DETECTED,
          {
            frameId,
            newParentFrameId,
            cycle,
            currentParentId: frame.parent_frame_id
          }
        );
      }
      const newParentFrame = this.frameDb.getFrame(newParentFrameId);
      if (newParentFrame) {
        const newDepth = newParentFrame.depth + 1;
        if (newDepth > this.maxFrameDepth) {
          throw new FrameError(
            `Cannot set parent: would exceed maximum frame depth`,
            ErrorCode.FRAME_STACK_OVERFLOW,
            {
              frameId,
              newParentFrameId,
              newDepth,
              maxDepth: this.maxFrameDepth
            }
          );
        }
      }
    }
    this.frameDb.updateFrame(frameId, {
      parent_frame_id: newParentFrameId
    });
    logger.info("Updated parent frame", {
      frameId,
      oldParentId: frame.parent_frame_id,
      newParentId: newParentFrameId
    });
  }
  /**
   * Validate the entire frame hierarchy for cycles and depth violations
   * @returns Validation result with any detected issues
   */
  validateFrameHierarchy() {
    const errors = [];
    const warnings = [];
    const allFrames = this.frameDb.getFramesByProject(this.projectId);
    for (const frame of allFrames) {
      if (frame.depth > this.maxFrameDepth) {
        errors.push(
          `Frame ${frame.frame_id} exceeds max depth: ${frame.depth} > ${this.maxFrameDepth}`
        );
      }
      if (frame.depth > this.maxFrameDepth * 0.8) {
        warnings.push(
          `Frame ${frame.frame_id} is deep in hierarchy: ${frame.depth}/${this.maxFrameDepth}`
        );
      }
    }
    const rootFrames = allFrames.filter((f) => !f.parent_frame_id);
    const visited = /* @__PURE__ */ new Set();
    const visiting = /* @__PURE__ */ new Set();
    const checkForCycle = (frameId) => {
      if (visiting.has(frameId)) {
        errors.push(`Cycle detected involving frame ${frameId}`);
        return true;
      }
      if (visited.has(frameId)) {
        return false;
      }
      visiting.add(frameId);
      const children = allFrames.filter((f) => f.parent_frame_id === frameId);
      for (const child of children) {
        if (checkForCycle(child.frame_id)) {
          return true;
        }
      }
      visiting.delete(frameId);
      visited.add(frameId);
      return false;
    };
    for (const root of rootFrames) {
      checkForCycle(root.frame_id);
    }
    return {
      isValid: errors.length === 0,
      errors,
      warnings
    };
  }
}
import {
  Frame as Frame2,
  FrameContext as FrameContext2,
  Anchor as Anchor2,
  Event as Event2,
  FrameType as FrameType2,
  FrameState as FrameState2,
  FrameCreationOptions as FrameCreationOptions2,
  FrameManagerConfig as FrameManagerConfig2,
  DigestResult as DigestResult2
} from "./frame-types.js";
export {
  Anchor2 as Anchor,
  DigestResult2 as DigestResult,
  Event2 as Event,
  Frame2 as Frame,
  FrameContext2 as FrameContext,
  FrameCreationOptions2 as FrameCreationOptions,
  FrameManagerConfig2 as FrameManagerConfig,
  FrameState2 as FrameState,
  FrameType2 as FrameType,
  RefactoredFrameManager
};
//# sourceMappingURL=refactored-frame-manager.js.map
