import {
  BUILDER_KICKOFF_PROMPT,
  PathAccessDeniedError,
  TurnMetrics,
  VERIFIER_KICKOFF_PROMPT,
  assembleAgentRequest,
  buildAgentReminder,
  createChatDoneEvent,
  createMessageStartEvent,
  executeSubAgent,
  findAgentById,
  getSubAgents,
  getToolRegistryForAgent,
  loadAllAgentsDefault,
  runTopLevelAgentLoop
} from "./chunk-ALH4KM2Y.js";
import {
  getCurrentContextWindowId,
  getEventStore
} from "./chunk-XKR3HCAL.js";
import {
  buildSnapshotFromSessionState
} from "./chunk-NONI4CRP.js";
import {
  logger
} from "./chunk-K44MW7JJ.js";

// src/server/sub-agents/verifier-helpers.ts
var MAX_CONSECUTIVE_VERIFIER_NUDGES = 10;
var VERIFIER_STALL_REASON = "Verifier stopped repeatedly before terminalizing verification after repeated nudges.";
function getCriteriaAwaitingVerification(criteria) {
  return criteria.filter((criterion) => criterion.status.type === "completed");
}
function buildVerifierNudgeContent(criteria) {
  const ids = criteria.map((criterion) => criterion.id).join(", ");
  return `You stopped before finalizing verification. ${criteria.length} criteria still need a terminal verification result. Use criterion with action "pass" or "fail" for each remaining criterion: ${ids}.`;
}
function buildVerifierRestartContent(criteria) {
  const ids = criteria.map((criterion) => criterion.id).join(", ");
  return `${VERIFIER_STALL_REASON} Leaving remaining criteria unchanged so verification can restart in a fresh window: ${ids}.`;
}
function createVerifierNudgeConfig() {
  return {
    maxConsecutiveNudges: MAX_CONSECUTIVE_VERIFIER_NUDGES,
    getCriteriaAwaiting: getCriteriaAwaitingVerification,
    buildNudgeContent: buildVerifierNudgeContent,
    buildRestartContent: buildVerifierRestartContent
  };
}

// src/server/chat/orchestrator.ts
function getCurrentWindowMessageOptions(sessionId) {
  const contextWindowId = getCurrentContextWindowId(sessionId);
  return contextWindowId ? { contextWindowId } : void 0;
}
function resolveStatsIdentity(options) {
  const model = options.llmClient.getModel();
  if (options.statsIdentity) {
    return {
      ...options.statsIdentity,
      model
    };
  }
  return {
    providerId: `provider:${model}`,
    providerName: "Unknown Provider",
    backend: "unknown",
    model
  };
}
async function runChatTurn(options) {
  const { sessionManager, sessionId } = options;
  const eventStore = getEventStore();
  const statsIdentity = resolveStatsIdentity(options);
  const session = sessionManager.requireSession(sessionId);
  const mode = session.mode;
  logger.debug("Starting chat turn", { sessionId, mode });
  const turnMetrics = new TurnMetrics();
  try {
    if (mode === "builder") {
      await runBuilderTurn(options, turnMetrics);
    } else {
      await runGenericAgentTurn(options, turnMetrics, mode);
    }
    const snapshot = buildSnapshot(sessionManager, sessionId, turnMetrics.buildStats(statsIdentity, mode));
    const snapshotEvent = eventStore.append(sessionId, { type: "turn.snapshot", data: snapshot });
    const deletedCount = eventStore.cleanupOldEvents(sessionId);
    if (deletedCount > 0) {
      logger.debug("Cleaned up old events after snapshot", { sessionId, deletedCount, snapshotSeq: snapshotEvent.seq });
    }
  } catch (error) {
    if (error instanceof PathAccessDeniedError) {
      const errorMsgId2 = crypto.randomUUID();
      const reasonText = error.reason === "sensitive_file" ? "sensitive files that may contain secrets" : error.reason === "both" ? "files outside the project and sensitive files" : "files outside the project directory";
      eventStore.append(sessionId, {
        type: "chat.error",
        data: {
          error: `User denied access to ${reasonText}.`,
          recoverable: false
        }
      });
      eventStore.append(
        sessionId,
        createMessageStartEvent(
          errorMsgId2,
          "user",
          `Access denied: ${error.paths.join(", ")}. If you need this file, explain why and ask the user for permission.`,
          {
            ...getCurrentWindowMessageOptions(sessionId) ?? {},
            isSystemGenerated: true,
            messageKind: "correction"
          }
        )
      );
      eventStore.append(sessionId, createChatDoneEvent(errorMsgId2, "error"));
      return;
    }
    if (error instanceof Error && error.message === "Aborted") {
      const snapshot = buildSnapshot(sessionManager, sessionId, turnMetrics.buildStats(statsIdentity, mode));
      eventStore.append(sessionId, { type: "turn.snapshot", data: snapshot });
      return;
    }
    logger.error("Chat turn error", { sessionId, mode, error });
    const errorMsgId = crypto.randomUUID();
    eventStore.append(sessionId, {
      type: "chat.error",
      data: {
        error: error instanceof Error ? error.message : "Unknown error",
        recoverable: false
      }
    });
    eventStore.append(
      sessionId,
      createMessageStartEvent(
        errorMsgId,
        "user",
        `Error: ${error instanceof Error ? error.message : "Unknown error"}`,
        {
          ...getCurrentWindowMessageOptions(sessionId) ?? {},
          isSystemGenerated: true,
          messageKind: "correction"
        }
      )
    );
    eventStore.append(sessionId, createChatDoneEvent(errorMsgId, "error"));
  } finally {
    eventStore.append(sessionId, { type: "running.changed", data: { isRunning: false } });
  }
}
function injectModeReminderIfNeeded(sessionManager, sessionId, agentId, allAgents, _onMessage) {
  const eventStore = getEventStore();
  const session = sessionManager.requireSession(sessionId);
  const lastModeReminder = session.executionState?.lastModeWithReminder;
  if (lastModeReminder === agentId) {
    return;
  }
  const agentDef = findAgentById(agentId, allAgents);
  if (!agentDef) return;
  const reminderContent = buildAgentReminder(agentDef);
  const reminderMsgId = crypto.randomUUID();
  const currentWindowMessageOptions = getCurrentContextWindowId(sessionId) ? { contextWindowId: getCurrentContextWindowId(sessionId) } : void 0;
  eventStore.append(sessionId, {
    type: "message.start",
    data: {
      messageId: reminderMsgId,
      role: "user",
      content: reminderContent,
      ...currentWindowMessageOptions ?? {},
      isSystemGenerated: true,
      messageKind: "auto-prompt",
      metadata: {
        type: "agent",
        name: agentDef.metadata.name ?? agentDef.metadata.id,
        color: agentDef.metadata.color ?? "#6b7280"
      }
    }
  });
  eventStore.append(sessionId, {
    type: "message.done",
    data: { messageId: reminderMsgId }
  });
  sessionManager.updateExecutionState(sessionId, {
    lastModeWithReminder: agentId
  });
}
async function runGenericAgentTurn(options, turnMetrics, agentId) {
  const statsIdentity = resolveStatsIdentity(options);
  const allAgents = await loadAllAgentsDefault();
  injectModeReminderIfNeeded(options.sessionManager, options.sessionId, agentId, allAgents, options.onMessage);
  const agentDef = findAgentById(agentId, allAgents) ?? findAgentById("planner", allAgents);
  const subAgentDefs = getSubAgents(allAgents);
  await runTopLevelAgentLoop(
    {
      mode: agentId,
      sessionManager: options.sessionManager,
      sessionId: options.sessionId,
      llmClient: options.llmClient,
      statsIdentity,
      signal: options.signal,
      onMessage: options.onMessage,
      assembleRequest: (input) => assembleAgentRequest({ ...input, agentDef, subAgentDefs, modelName: options.llmClient.getModel() }),
      getToolRegistry: () => getToolRegistryForAgent(agentDef)
    },
    turnMetrics
  );
}
function filterToolRegistryForStepDone(baseRegistry, _injectStepDone) {
  return baseRegistry;
}
async function runBuilderTurn(options, turnMetrics) {
  const { sessionManager, sessionId } = options;
  const statsIdentity = resolveStatsIdentity(options);
  const eventStore = getEventStore();
  const allAgents = await loadAllAgentsDefault();
  injectModeReminderIfNeeded(options.sessionManager, options.sessionId, "builder", allAgents, options.onMessage);
  const builderDef = findAgentById("builder", allAgents);
  const subAgentDefs = getSubAgents(allAgents);
  let stepDoneCalled = false;
  return {
    ...await runTopLevelAgentLoop(
      {
        mode: "builder",
        sessionManager,
        sessionId,
        llmClient: options.llmClient,
        statsIdentity,
        signal: options.signal,
        onMessage: options.onMessage,
        assembleRequest: (input) => assembleAgentRequest({
          ...input,
          agentDef: builderDef,
          subAgentDefs,
          modelName: options.llmClient.getModel()
        }),
        getToolRegistry: () => {
          const baseRegistry = getToolRegistryForAgent(builderDef);
          return filterToolRegistryForStepDone(baseRegistry, options.injectStepDone === true);
        },
        onToolExecuted: (toolCall, toolResult) => {
          if (toolCall.name === "step_done" && toolResult.success) {
            stepDoneCalled = true;
          }
          if (toolResult.success && ["write_file", "edit_file"].includes(toolCall.name)) {
            const path = toolCall.arguments["path"];
            sessionManager.addModifiedFile(sessionId, path);
          }
        },
        injectKickoff: () => {
          if (options.injectBuilderKickoff !== true) return;
          const session = sessionManager.requireSession(sessionId);
          const currentWindowMessageOptions = getCurrentContextWindowId(sessionId) ? { contextWindowId: getCurrentContextWindowId(sessionId) } : void 0;
          const events = eventStore.getEvents(sessionId);
          const hasBuilderKickoff = events.some((e) => {
            if (e.type !== "message.start") return false;
            const data = e.data;
            return data.messageKind === "auto-prompt" && data.content?.includes("fulfil the");
          });
          if (!hasBuilderKickoff) {
            const kickoffMsgId = crypto.randomUUID();
            const kickoffContent = BUILDER_KICKOFF_PROMPT(session.criteria.length);
            const msgMetadata = { type: "workflow", name: "Workflow", color: "#f59e0b" };
            eventStore.append(
              sessionId,
              createMessageStartEvent(kickoffMsgId, "user", kickoffContent, {
                ...currentWindowMessageOptions ?? {},
                isSystemGenerated: true,
                messageKind: "auto-prompt",
                metadata: msgMetadata
              })
            );
            eventStore.append(sessionId, { type: "message.done", data: { messageId: kickoffMsgId } });
          }
        }
      },
      turnMetrics
    ),
    stepDoneCalled
  };
}
async function runVerifierTurn(options, turnMetrics) {
  const { sessionManager, sessionId, llmClient, signal, onMessage } = options;
  const statsIdentity = resolveStatsIdentity(options);
  const session = sessionManager.requireSession(sessionId);
  const toVerify = session.criteria.filter((c) => c.status.type === "completed");
  if (toVerify.length === 0) {
    logger.debug("Nothing to verify", { sessionId });
    return { allPassed: true, failed: [] };
  }
  const allAgents = await loadAllAgentsDefault();
  const verifierDef = findAgentById("verifier", allAgents);
  const toolRegistry = getToolRegistryForAgent(verifierDef);
  const result = await executeSubAgent({
    subAgentType: "verifier",
    prompt: VERIFIER_KICKOFF_PROMPT,
    sessionManager,
    sessionId,
    llmClient,
    toolRegistry,
    turnMetrics,
    statsIdentity,
    signal,
    onMessage,
    nudgeConfig: createVerifierNudgeConfig()
  });
  return {
    allPassed: result.allPassed ?? true,
    failed: result.failed ?? [],
    content: result.content
  };
}
function buildSnapshot(sessionManager, sessionId, _lastStats) {
  const eventStore = getEventStore();
  const session = sessionManager.requireSession(sessionId);
  const events = eventStore.getEvents(sessionId);
  const latestSeq = eventStore.getLatestSeq(sessionId) ?? 0;
  const cachedPrompt = sessionManager.getCachedPrompt(sessionId);
  return buildSnapshotFromSessionState({
    session,
    events,
    latestSeq,
    ...cachedPrompt ? { cachedSystemPrompt: cachedPrompt.systemPrompt, dynamicContextHash: cachedPrompt.hash } : {}
  });
}

export {
  createVerifierNudgeConfig,
  runChatTurn,
  filterToolRegistryForStepDone,
  runBuilderTurn,
  runVerifierTurn
};
//# sourceMappingURL=chunk-UFY4I643.js.map