import {
  initialRuntimeState,
  reduceRuntimeState
} from "./chunk-5N6QO6NC.js";
import {
  createTimelineSequencer
} from "./chunk-VK2Y4OK3.js";

// ../packages/local-runtime/dist/chunk-OGKJ6WLF.js
var PushAgentEventStream = class {
  connected = false;
  listeners = null;
  connect(onEvent, onError, onClose) {
    this.listeners = { onEvent, onError, onClose };
    this.connected = true;
  }
  disconnect() {
    this.listeners = null;
    this.connected = false;
  }
  isConnected() {
    return this.connected;
  }
  emit(event) {
    this.listeners?.onEvent(event);
  }
  fail(error) {
    this.listeners?.onError?.(error);
  }
  close() {
    this.connected = false;
    this.listeners?.onClose?.();
  }
};
function parseJsonLine(line) {
  const trimmed = line.trim();
  if (!trimmed) return null;
  try {
    return JSON.parse(trimmed);
  } catch {
    return null;
  }
}
function asRecord(value) {
  return value && typeof value === "object" ? value : {};
}
function getText(value) {
  return typeof value === "string" && value.length > 0 ? value : void 0;
}
function normalizeUsage(raw) {
  const inputTokens = typeof raw.input_tokens === "number" ? raw.input_tokens : typeof raw.inputTokens === "number" ? raw.inputTokens : 0;
  const outputTokens = typeof raw.output_tokens === "number" ? raw.output_tokens : typeof raw.outputTokens === "number" ? raw.outputTokens : 0;
  return { inputTokens, outputTokens };
}
function mapClaudeStreamJsonLine(line) {
  const payload = asRecord(parseJsonLine(line));
  const type = getText(payload.type);
  if (!type) return [];
  if (type === "system" && payload.subtype === "init") {
    return [{ type: "status", message: "Claude session initialized" }];
  }
  if (type === "stream_event") {
    const event = asRecord(payload.event);
    if (event.type === "content_block_delta") {
      const delta = asRecord(event.delta);
      const text = getText(delta.text);
      if (text) {
        return [{
          type: "text_delta",
          text,
          turnId: getText(asRecord(payload.message).id) ?? getText(payload.message_id) ?? "msg_1"
        }];
      }
    }
    return [];
  }
  if (type === "assistant") {
    const message = asRecord(payload.message);
    const turnId = getText(message.id);
    const content = Array.isArray(message.content) ? message.content.map(asRecord) : [];
    const events = [];
    for (const item of content) {
      if (item.type === "tool_use") {
        const toolUseId = getText(item.id);
        const toolName = getText(item.name);
        if (toolUseId && toolName) {
          events.push({
            type: "tool_start",
            toolName,
            toolUseId,
            input: asRecord(item.input),
            turnId
          });
        }
      } else if (item.type === "text") {
        const text = getText(item.text);
        if (text) {
          events.push({
            type: "text_complete",
            text,
            isIntermediate: message.stop_reason === "tool_use",
            turnId
          });
        }
      }
    }
    return events;
  }
  if (type === "result") {
    if (payload.subtype && payload.subtype !== "success") {
      return [{ type: "error", message: `Claude finished with ${String(payload.subtype)}` }, { type: "complete" }];
    }
    return [{ type: "complete", usage: normalizeUsage(asRecord(payload.usage)) }];
  }
  if (type === "error") {
    return [{ type: "error", message: getText(payload.message) ?? "Claude stream error" }];
  }
  return [];
}
function mapCodexExecJsonLine(line) {
  const payload = asRecord(parseJsonLine(line));
  const type = getText(payload.type);
  if (!type) return [];
  if (type === "session.started" || type === "session_started" || type === "thread.started" || type === "thread_started") {
    return [{ type: "status", message: "Codex session initialized" }];
  }
  if (type === "turn.started" || type === "turn_started") {
    return [{ type: "status", message: "Codex turn started" }];
  }
  if (type === "item.started" || type === "item_started") {
    const item = asRecord(payload.item);
    const itemType = getText(item.type);
    if (itemType === "command_execution" || itemType === "commandExecution") {
      const toolUseId = getText(item.id) ?? getText(payload.item_id) ?? `tool-${Date.now()}`;
      const command = getText(item.command);
      return [{
        type: "tool_start",
        toolName: "Bash",
        toolUseId,
        input: command ? { command } : asRecord(item.arguments),
        turnId: getText(payload.turn_id) ?? getText(payload.turnId)
      }];
    }
    return [];
  }
  if (type === "item.completed" || type === "item_completed") {
    const item = asRecord(payload.item);
    const itemType = getText(item.type);
    if (itemType === "agent_message" || itemType === "agentMessage") {
      const text = getText(item.text) ?? getText(item.message);
      return text ? [{
        type: "text_complete",
        text,
        isIntermediate: false,
        turnId: getText(item.id) ?? getText(payload.turn_id) ?? getText(payload.turnId)
      }] : [];
    }
    if (itemType === "command_execution" || itemType === "commandExecution") {
      const toolUseId = getText(item.id) ?? getText(payload.item_id) ?? `tool-${Date.now()}`;
      const exitCode = typeof item.exit_code === "number" ? item.exit_code : typeof item.exitCode === "number" ? item.exitCode : 0;
      return [{
        type: "tool_result",
        toolName: "Bash",
        toolUseId,
        result: getText(item.aggregated_output) ?? getText(item.aggregatedOutput) ?? getText(item.output) ?? "",
        isError: exitCode !== 0 || item.is_error === true,
        turnId: getText(payload.turn_id) ?? getText(payload.turnId)
      }];
    }
    return [];
  }
  if (type === "agent_message_delta" || type === "message_delta" || type === "response.output_text.delta") {
    const text = getText(payload.delta) ?? getText(payload.text);
    return text ? [{ type: "text_delta", text }] : [];
  }
  if (type === "agent_message" || type === "message" || type === "response.output_text.done") {
    const text = getText(payload.message) ?? getText(payload.text);
    return text ? [{ type: "text_complete", text, isIntermediate: false }] : [];
  }
  if (type === "exec_command_begin" || type === "tool_call_begin") {
    const toolUseId = getText(payload.call_id) ?? getText(payload.id) ?? `tool-${Date.now()}`;
    const command = getText(payload.command);
    return [{
      type: "tool_start",
      toolName: getText(payload.tool_name) ?? "Bash",
      toolUseId,
      input: command ? { command } : asRecord(payload.arguments)
    }];
  }
  if (type === "exec_command_end" || type === "tool_call_end") {
    const toolUseId = getText(payload.call_id) ?? getText(payload.id) ?? `tool-${Date.now()}`;
    const exitCode = typeof payload.exit_code === "number" ? payload.exit_code : 0;
    return [{
      type: "tool_result",
      toolName: getText(payload.tool_name) ?? "Bash",
      toolUseId,
      result: getText(payload.output) ?? getText(payload.result) ?? "",
      isError: exitCode !== 0 || payload.is_error === true
    }];
  }
  if (type === "turn_completed" || type === "turn.completed" || type === "task_complete" || type === "response.completed") {
    return [{ type: "complete", usage: normalizeUsage(asRecord(payload.usage)) }];
  }
  if (type === "error") {
    return [{ type: "error", message: getText(payload.message) ?? "Codex stream error" }];
  }
  return [];
}
function createLocalTimelineProjector(options) {
  const sequencer = createTimelineSequencer(options);
  let lastTurnId;
  return {
    project(event) {
      const items = mapAgentEventToTimelineItems(event, lastTurnId);
      const eventTurnId = turnIdFromAgentEvent(event);
      const itemTurnId = items.map((item) => "turnId" in item ? item.turnId : void 0).find((turnId) => typeof turnId === "string");
      if (eventTurnId ?? itemTurnId) lastTurnId = eventTurnId ?? itemTurnId;
      return items.map((item) => append(sequencer, item, event.type));
    }
  };
}
function append(sequencer, item, providerEventType) {
  return sequencer.append(item, { providerEventType });
}
function mapAgentEventToTimelineItems(event, lastTurnId) {
  switch (event.type) {
    case "status":
    case "info":
      return [{ type: "session_status", status: event.message }];
    case "text_delta": {
      const turnId = event.turnId ?? lastTurnId ?? "turn-local";
      return [{
        type: "assistant_message_delta",
        text: event.text,
        messageId: messageIdForTurn(turnId),
        turnId
      }];
    }
    case "text_complete": {
      const turnId = event.turnId ?? lastTurnId ?? "turn-local";
      return [{
        type: "assistant_message",
        text: event.text,
        messageId: messageIdForTurn(turnId),
        turnId
      }];
    }
    case "reasoning_delta": {
      const turnId = event.turnId ?? lastTurnId ?? "turn-local";
      return [{
        type: "assistant_message_delta",
        text: event.text,
        messageId: messageIdForTurn(turnId),
        turnId
      }];
    }
    case "reasoning": {
      const turnId = event.turnId ?? lastTurnId ?? "turn-local";
      return [{
        type: "assistant_message",
        text: event.text,
        messageId: messageIdForTurn(turnId),
        turnId
      }];
    }
    case "tool_start":
      return [{
        type: "tool_call",
        callId: event.toolUseId,
        name: event.toolName,
        status: "running",
        detail: { input: event.input },
        turnId: event.turnId
      }];
    case "tool_result":
      return [{
        type: "tool_result",
        callId: event.toolUseId,
        result: event.result,
        isError: event.isError,
        turnId: event.turnId
      }];
    case "permission_request":
      return [{
        type: "permission_requested",
        request: {
          requestId: event.requestId,
          toolName: event.toolName,
          input: { command: event.command },
          reason: event.reason
        }
      }];
    case "permission_response":
      return [{
        type: "permission_resolved",
        requestId: event.requestId,
        resolution: {
          allowed: event.allowed,
          remember: event.remember ?? false
        }
      }];
    case "complete": {
      const items = [];
      if (lastTurnId) {
        items.push({
          type: "turn_completed",
          turnId: lastTurnId,
          usage: event.usage
        });
      }
      items.push({ type: "session_status", status: "ready" });
      return items;
    }
    case "error":
      if (lastTurnId) {
        return [{
          type: "turn_failed",
          turnId: lastTurnId,
          error: { message: event.message }
        }];
      }
      return [{ type: "session_status", status: "failed" }];
    case "typed_error":
      if (lastTurnId) {
        return [{
          type: "turn_failed",
          turnId: lastTurnId,
          error: event.error
        }];
      }
      return [{ type: "session_status", status: "failed" }];
    case "source_activated":
      return [{
        type: "source_state_changed",
        source: {
          sourceSlug: event.sourceSlug,
          state: "active",
          originalMessage: event.originalMessage
        }
      }];
    case "usage_update":
      return [{ type: "session_status", status: "usage_update" }];
    case "working_directory_changed":
      return [{
        type: "session_status",
        status: `working_directory:${event.workingDirectory}`
      }];
    case "compaction_started":
      return [{ type: "compaction_started" }];
    case "compaction_boundary":
      return [{ type: "compaction_boundary", summary: event.summary }];
    case "task_backgrounded":
    case "shell_backgrounded":
    case "task_progress":
    case "task_completed":
    case "shell_killed":
    case "steer_undelivered":
      return [{ type: "session_status", status: event.type }];
    default:
      return [];
  }
}
function turnIdFromAgentEvent(event) {
  if ("turnId" in event) return event.turnId;
  return void 0;
}
function messageIdForTurn(turnId) {
  return `${turnId}:assistant`;
}
function createFakeLocalAgentSession(options) {
  const events = new PushAgentEventStream();
  let state = initialRuntimeState;
  function dispatch(action) {
    state = reduceRuntimeState(state, action);
  }
  async function runScript() {
    events.emit({ type: "status", message: `${options.provider} runtime accepted message` });
    for (const event of options.script) {
      if (event.type === "permission_request") {
        dispatch({ type: "permission_request", requestId: event.requestId });
      }
      events.emit(event);
      if (event.type === "complete") {
        dispatch({ type: "complete" });
      }
    }
  }
  return {
    sessionId: options.sessionId ?? `local-${options.provider}-${Date.now()}`,
    provider: options.provider,
    events,
    async preflight() {
      dispatch({ type: "preflight_ok" });
      return {
        mode: "provider-owned",
        configured: true,
        source: "fake-local-runtime"
      };
    },
    getState() {
      return state;
    },
    commands: {
      async sendMessage(message, _sendOptions) {
        dispatch({ type: "send_message", message });
        await runScript();
      },
      async abort(reason) {
        dispatch({ type: "abort", reason });
        events.emit({ type: "error", message: reason ?? "Aborted" });
        events.emit({ type: "complete" });
      },
      async respondToPermission(_requestId, _allowed, _remember) {
        dispatch({ type: "permission_response" });
      },
      async dispose() {
        dispatch({ type: "dispose" });
        events.close();
      }
    }
  };
}
function generateTraceTurnId() {
  return `turn-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
}
function generateTraceToolUseId() {
  return `tool-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
}
var TraceToolIndex = class {
  index = /* @__PURE__ */ new Map();
  append(id, name, input) {
    this.index.set(id, { id, name, input, matched: false });
  }
  find(id) {
    return this.index.get(id);
  }
  markMatched(id) {
    const entry = this.index.get(id);
    if (entry) {
      entry.matched = true;
    }
  }
  isMatched(id) {
    return this.index.get(id)?.matched ?? false;
  }
  has(id) {
    return this.index.has(id);
  }
  clear() {
    this.index.clear();
  }
  /** Get all unmatched tool starts (for detecting orphaned tool calls) */
  unmatched() {
    return Array.from(this.index.values()).filter((entry) => !entry.matched);
  }
};
var READ_PATTERNS = [
  // cat file
  {
    regex: /^cat\s+['"]?([^'"\s]+)['"]?\s*$/,
    extract: (m) => ({ filePath: m[1], originalCommand: m[0] })
  },
  // head -n N file / head -N file
  {
    regex: /^head\s+-n\s+(\d+)\s+['"]?([^'"\s]+)['"]?\s*$/,
    extract: (m) => ({
      filePath: m[2],
      endLine: parseInt(m[1], 10),
      originalCommand: m[0]
    })
  },
  {
    regex: /^head\s+-(\d+)\s+['"]?([^'"\s]+)['"]?\s*$/,
    extract: (m) => ({
      filePath: m[2],
      endLine: parseInt(m[1], 10),
      originalCommand: m[0]
    })
  },
  // tail -n N file
  {
    regex: /^tail\s+-n\s+(\d+)\s+['"]?([^'"\s]+)['"]?\s*$/,
    extract: (m) => ({
      filePath: m[2],
      startLine: -parseInt(m[1], 10),
      // negative = last N lines
      originalCommand: m[0]
    })
  },
  // sed -n 'start,end' file
  {
    regex: /^sed\s+-n\s+'(\d+),(\d+)p'\s+['"]?([^'"\s]+)['"]?\s*$/,
    extract: (m) => ({
      filePath: m[3],
      startLine: parseInt(m[1], 10),
      endLine: parseInt(m[2], 10),
      originalCommand: m[0]
    })
  },
  // sed -n 'startp' file
  {
    regex: /^sed\s+-n\s+'(\d+)p'\s+['"]?([^'"\s]+)['"]?\s*$/,
    extract: (m) => ({
      filePath: m[2],
      startLine: parseInt(m[1], 10),
      endLine: parseInt(m[1], 10),
      originalCommand: m[0]
    })
  }
];
function parseTraceReadCommand(command) {
  const stripped = command.replace(/^bash\s+-[lc]+\s+/, "").trim();
  for (const pattern of READ_PATTERNS) {
    const match = stripped.match(pattern.regex);
    if (match) {
      return pattern.extract(match);
    }
  }
  return null;
}
var TraceEventAdapter = class {
  turnIndex = 0;
  currentTurnId = null;
  // Shared state maps — reset on each turn
  commandOutput = /* @__PURE__ */ new Map();
  readCommands = /* @__PURE__ */ new Map();
  blockReasons = /* @__PURE__ */ new Map();
  toolIndex = new TraceToolIndex();
  /**
   * Start a new turn — resets shared state and calls subclass hook.
   */
  startTurn(turnId) {
    this.turnIndex++;
    this.commandOutput.clear();
    this.readCommands.clear();
    this.blockReasons.clear();
    this.toolIndex.clear();
    this.currentTurnId = turnId || generateTraceTurnId();
    this.onTurnStart();
  }
  setBlockReason(id, reason) {
    this.blockReasons.set(id, reason);
  }
  consumeBlockReason(...keys) {
    for (const key of keys) {
      const reason = this.blockReasons.get(key);
      if (reason !== void 0) {
        this.blockReasons.delete(key);
        return reason;
      }
    }
    return void 0;
  }
  classifyReadCommand(id, command) {
    const readInfo = parseTraceReadCommand(command);
    if (readInfo) {
      this.readCommands.set(id, readInfo);
    }
    return readInfo;
  }
  consumeReadCommand(id) {
    const info = this.readCommands.get(id);
    if (info) {
      this.readCommands.delete(id);
    }
    return info;
  }
  accumulateOutput(id, delta) {
    const current = this.commandOutput.get(id) || "";
    this.commandOutput.set(id, current + delta);
  }
  consumeOutput(id) {
    const output = this.commandOutput.get(id);
    if (output !== void 0) {
      this.commandOutput.delete(id);
    }
    return output;
  }
  createToolStart(id, toolName, input, intent, displayName, parentToolUseId) {
    return {
      type: "tool_start",
      toolName,
      toolUseId: id,
      input,
      intent,
      displayName,
      turnId: this.currentTurnId || void 0,
      parentToolUseId
    };
  }
  createToolResult(id, toolName, result, isError, parentToolUseId) {
    return {
      type: "tool_result",
      toolUseId: id,
      toolName,
      result,
      isError,
      turnId: this.currentTurnId || void 0,
      parentToolUseId
    };
  }
  createReadToolStart(id, readInfo, intent) {
    return this.createToolStart(
      id,
      "Read",
      {
        file_path: readInfo.filePath,
        offset: readInfo.startLine,
        limit: readInfo.endLine ? readInfo.endLine - (readInfo.startLine || 1) + 1 : void 0,
        _command: readInfo.originalCommand
      },
      intent,
      "Read File"
    );
  }
  /**
   * Build an MCP tool name from server and tool names.
   */
  buildMcpToolName(serverName, toolName) {
    if (toolName.startsWith("mcp__")) return toolName;
    return `mcp__${serverName}__${toolName}`;
  }
};
var ClaudeStdoutAdapter = class extends TraceEventAdapter {
  hasFinalResponse = false;
  onTurnStart() {
    this.hasFinalResponse = false;
  }
  /**
   * Parse claude -p stdout + stderr into AgentEvent[].
   *
   * Since claude -p output is mostly unstructured plain text,
   * we do a best-effort extraction of tool-related patterns
   * and map everything else to text_complete / status / error events.
   */
  parseOutput(stdout, stderr) {
    const events = [];
    this.startTurn();
    if (stderr.trim()) {
      const errorLines = stderr.split("\n").filter((l) => l.trim());
      for (const line of errorLines) {
        if (line.includes("rate_limited") || line.includes("Rate limit") || line.includes("429")) {
          events.push({ type: "error", message: "Rate limited \u2014 please wait and retry" });
        } else if (line.includes("invalid_api_key") || line.includes("Authentication") || line.includes("401") || line.includes("403")) {
          events.push({ type: "error", message: "Authentication error \u2014 check your API key" });
        } else if (line.includes("context_length_exceeded") || line.includes("too long")) {
          events.push({ type: "error", message: "Context limit exceeded" });
        } else {
          events.push({ type: "status", message: line.trim() });
        }
      }
    }
    const stdoutLines = stdout.split("\n");
    let responseText = "";
    let currentTool = null;
    let inXmlToolUse = false;
    let xmlToolName = "";
    let xmlToolInput = "";
    let xmlToolResult = "";
    let inXmlToolResult = false;
    for (const line of stdoutLines) {
      const xmlToolStartMatch = line.match(/<tool_use>\s*([\w.]+)/i);
      if (xmlToolStartMatch) {
        if (responseText.trim()) {
          events.push({
            type: "text_complete",
            text: responseText.trim(),
            isIntermediate: true,
            turnId: this.currentTurnId || void 0
          });
          responseText = "";
        }
        inXmlToolUse = true;
        xmlToolName = xmlToolStartMatch[1];
        xmlToolInput = "";
        continue;
      }
      if (inXmlToolUse && line.match(/<\/tool_use>/i)) {
        inXmlToolUse = false;
        const toolId = generateTraceToolUseId();
        let parsedInput = {};
        try {
          parsedInput = JSON.parse(xmlToolInput.trim());
        } catch {
          parsedInput = { raw_input: xmlToolInput.trim() };
        }
        events.push(this.createToolStart(toolId, xmlToolName, parsedInput));
        this.toolIndex.append(toolId, xmlToolName, parsedInput);
        currentTool = { id: toolId, name: xmlToolName, input: parsedInput, outputLines: [] };
        continue;
      }
      if (inXmlToolUse) {
        xmlToolInput += line + "\n";
        continue;
      }
      const xmlResultStartMatch = line.match(/<tool_result>/i);
      if (xmlResultStartMatch) {
        inXmlToolResult = true;
        xmlToolResult = "";
        continue;
      }
      if (inXmlToolResult && line.match(/<\/tool_result>/i)) {
        inXmlToolResult = false;
        if (currentTool) {
          events.push(
            this.createToolResult(currentTool.id, currentTool.name, xmlToolResult.trim(), false)
          );
          currentTool = null;
        }
        xmlToolResult = "";
        continue;
      }
      if (inXmlToolResult) {
        xmlToolResult += line + "\n";
        continue;
      }
      const toolStartMatch = matchToolStartPattern(line);
      if (toolStartMatch) {
        if (responseText.trim()) {
          events.push({
            type: "text_complete",
            text: responseText.trim(),
            isIntermediate: true,
            turnId: this.currentTurnId || void 0
          });
          responseText = "";
        }
        currentTool = {
          id: generateTraceToolUseId(),
          name: toolStartMatch.name,
          input: toolStartMatch.input,
          outputLines: []
        };
        events.push(
          this.createToolStart(currentTool.id, currentTool.name, currentTool.input)
        );
        this.toolIndex.append(currentTool.id, currentTool.name, currentTool.input);
        continue;
      }
      const toolEndMatch = matchToolEndPattern(line);
      if (toolEndMatch && currentTool) {
        events.push(
          this.createToolResult(
            currentTool.id,
            currentTool.name,
            currentTool.outputLines.join("\n").trim() || toolEndMatch.result,
            toolEndMatch.isError
          )
        );
        currentTool = null;
        continue;
      }
      if (currentTool) {
        currentTool.outputLines.push(line);
      } else {
        responseText += line + "\n";
      }
    }
    if (currentTool) {
      events.push(
        this.createToolResult(
          currentTool.id,
          currentTool.name,
          currentTool.outputLines.join("\n").trim(),
          false
        )
      );
    }
    if (responseText.trim()) {
      events.push({
        type: "text_complete",
        text: responseText.trim(),
        isIntermediate: false,
        turnId: this.currentTurnId || void 0
      });
      this.hasFinalResponse = true;
    }
    events.push({ type: "complete" });
    return events;
  }
};
function matchToolStartPattern(line) {
  const trimmed = line.trim();
  const cmdMatch = trimmed.match(/^Running command:\s+(.+)$/i) || trimmed.match(/^Executing:\s+(.+)$/i) || trimmed.match(/^Running bash command:\s+(.+)$/i);
  if (cmdMatch) {
    return { name: "Bash", input: { command: cmdMatch[1] } };
  }
  const readMatch = trimmed.match(/^Reading file:\s+(.+)$/i) || trimmed.match(/^Read:\s+(.+)$/i);
  if (readMatch) {
    return { name: "Read", input: { file_path: readMatch[1] } };
  }
  const writeMatch = trimmed.match(/^Writing file:\s+(.+)$/i) || trimmed.match(/^Edit:\s+(.+)$/i) || trimmed.match(/^Writing:\s+(.+)$/i);
  if (writeMatch) {
    return { name: "Edit", input: { file_path: writeMatch[1] } };
  }
  const searchMatch = trimmed.match(/^Searching for:\s+(.+)$/i) || trimmed.match(/^Search:\s+(.+)$/i);
  if (searchMatch) {
    return { name: "Search", input: { query: searchMatch[1] } };
  }
  return null;
}
function matchToolEndPattern(line) {
  const trimmed = line.trim();
  if (/^Command (completed|finished|done)/i.test(trimmed) || /^Done$/i.test(trimmed)) {
    return { result: trimmed, isError: false };
  }
  if (/^Command failed/i.test(trimmed) || /^Error:/i.test(trimmed)) {
    return { result: trimmed, isError: true };
  }
  if (/^File (written|read|updated) (successfully|complete)/i.test(trimmed)) {
    return { result: trimmed, isError: false };
  }
  return null;
}
function parseClaudeStdoutTrace(stdout, stderr) {
  return new ClaudeStdoutAdapter().parseOutput(stdout, stderr);
}
var CodexRolloutAdapter = class extends TraceEventAdapter {
  // Per-turn state for deduplication
  emittedEventMsgIds = /* @__PURE__ */ new Set();
  pendingAssistantText = null;
  pendingAssistantTurnId = null;
  onTurnStart() {
    this.emittedEventMsgIds.clear();
    this.pendingAssistantText = null;
    this.pendingAssistantTurnId = null;
  }
  /**
   * Parse a complete rollout JSONL string into AgentEvent[].
   * Each line is a JSON object representing a Codex event.
   */
  parseRollout(rolloutJsonl) {
    const events = [];
    const lines = rolloutJsonl.split("\n").filter((l) => l.trim());
    this.startTurn();
    for (const line of lines) {
      try {
        const obj = JSON.parse(line);
        const parsed = this.adaptRolloutEvent(obj);
        events.push(...parsed);
      } catch {
      }
    }
    if (this.pendingAssistantText) {
      events.push({
        type: "text_complete",
        text: this.pendingAssistantText,
        isIntermediate: false,
        turnId: this.pendingAssistantTurnId || this.currentTurnId || void 0
      });
      this.pendingAssistantText = null;
    }
    const hasComplete = events.some((e) => e.type === "complete");
    if (!hasComplete && events.length > 0) {
      events.push({ type: "complete" });
    }
    return events;
  }
  /**
   * Adapt a single Codex rollout event to AgentEvent[].
   */
  adaptRolloutEvent(event) {
    const events = [];
    switch (event.type) {
      // ====================================================================
      // Text & reasoning events
      // ====================================================================
      case "response_item": {
        const item = event;
        if (item.id && this.emittedEventMsgIds.has(item.id)) {
          break;
        }
        if (item.role === "assistant") {
          const text = extractTextFromContent(item.content);
          if (text) {
            const isReasoning = item.metadata?.reasoning === true;
            const isIntermediate = isReasoning || hasToolUseInContent(item.content);
            if (isIntermediate) {
              events.push({
                type: "text_complete",
                text,
                isIntermediate: true,
                turnId: this.currentTurnId || void 0
              });
            } else {
              this.pendingAssistantText = text;
              this.pendingAssistantTurnId = this.currentTurnId;
            }
          }
          const toolUses = extractToolUsesFromContent(item.content);
          for (const tu of toolUses) {
            this.toolIndex.append(tu.id, tu.name, tu.input);
            events.push(this.createToolStart(tu.id, tu.name, tu.input, void 0, void 0));
          }
        }
        if (item.role === "user" && isSyntheticMessage(item)) {
          break;
        }
        break;
      }
      case "event_msg": {
        const msg = event;
        if (msg.id) {
          this.emittedEventMsgIds.add(msg.id);
        }
        if (msg.role === "assistant" && msg.message) {
          events.push({
            type: "text_complete",
            text: msg.message,
            isIntermediate: false,
            turnId: this.currentTurnId || void 0
          });
        }
        break;
      }
      case "agent_message_delta": {
        const delta = event;
        if (delta.delta) {
          events.push({
            type: "text_delta",
            text: delta.delta,
            turnId: this.currentTurnId || void 0
          });
        }
        break;
      }
      case "agent_reasoning": {
        const reasoning = event;
        if (reasoning.text) {
          events.push({
            type: "text_complete",
            text: reasoning.text,
            isIntermediate: true,
            turnId: this.currentTurnId || void 0
          });
        }
        break;
      }
      case "agent_reasoning_delta": {
        const delta = event;
        if (delta.delta) {
          events.push({
            type: "text_delta",
            text: delta.delta,
            turnId: this.currentTurnId || void 0
          });
        }
        break;
      }
      // ====================================================================
      // Command execution events
      // ====================================================================
      case "exec_command_begin": {
        const cmd = event;
        const command = Array.isArray(cmd.command) ? cmd.command.join(" ") : String(cmd.command ?? "");
        const cwd = cmd.cwd ?? "";
        const readInfo = this.classifyReadCommand(cmd.call_id, command);
        if (readInfo) {
          events.push(this.createReadToolStart(cmd.call_id, readInfo));
        } else {
          events.push(
            this.createToolStart(cmd.call_id, "Bash", {
              command,
              cwd
            }, void 0, "Execute Command")
          );
        }
        this.toolIndex.append(cmd.call_id, "Bash", { command, cwd });
        break;
      }
      case "exec_command_output_delta": {
        const delta = event;
        const decoded = decodeBase64Chunk(delta.chunk);
        if (decoded) {
          this.accumulateOutput(delta.call_id, decoded);
        }
        break;
      }
      case "exec_command_end": {
        const cmdEnd = event;
        const accumulated = this.consumeOutput(cmdEnd.call_id);
        const output = accumulated ?? cmdEnd.stdout ?? cmdEnd.formatted_output ?? "";
        const cleanOutput = stripShellEnvelope(output);
        const isError = cmdEnd.exit_code !== 0;
        const readInfo = this.consumeReadCommand(cmdEnd.call_id);
        events.push(
          this.createToolResult(
            cmdEnd.call_id,
            readInfo ? "Read" : "Bash",
            cleanOutput,
            isError
          )
        );
        this.pendingAssistantText = null;
        break;
      }
      // ====================================================================
      // Patch / file modification events
      // ====================================================================
      case "apply_patch_approval_request":
      case "patch_apply_begin": {
        const patch = event;
        const callId = patch.call_id ?? `patch-${this.turnIndex}`;
        const changes = patch.changes ?? {};
        const filePaths = Object.keys(changes);
        const input = {
          changes,
          file_paths: filePaths
        };
        if (filePaths.length === 1) {
          input.file_path = filePaths[0];
          const change = changes[filePaths[0]];
          if (change && typeof change === "object") {
            if ("unified_diff" in change) input.unified_diff = change.unified_diff;
            if ("content" in change) input.content = change.content;
          }
        }
        events.push(
          this.createToolStart(callId, "Edit", input, void 0, "Apply Patch")
        );
        this.toolIndex.append(callId, "Edit", input);
        break;
      }
      case "patch_apply_end": {
        const end = event;
        const callId = end.call_id ?? `patch-${this.turnIndex}`;
        const result = end.stdout ?? (end.success ? "Patch applied successfully" : end.error ?? "Patch failed");
        events.push(
          this.createToolResult(callId, "Edit", result, !end.success)
        );
        break;
      }
      // ====================================================================
      // MCP tool events
      // ====================================================================
      case "mcp_tool_call_begin": {
        const mcp = event;
        const callId = mcp.call_id ?? `mcp-${this.turnIndex}`;
        const invocation = mcp.invocation ?? {};
        const toolName = this.buildMcpToolName(invocation.server ?? "unknown", invocation.tool ?? "unknown");
        const input = invocation.arguments ?? {};
        events.push(
          this.createToolStart(callId, toolName, input, void 0, invocation.tool ?? toolName)
        );
        this.toolIndex.append(callId, toolName, input);
        break;
      }
      case "mcp_tool_call_end": {
        const mcpEnd = event;
        const callId = mcpEnd.call_id ?? `mcp-${this.turnIndex}`;
        const result = mcpEnd.result ?? (mcpEnd.error ?? "MCP call completed");
        const isError = Boolean(mcpEnd.error);
        events.push(
          this.createToolResult(callId, "MCP", typeof result === "string" ? result : JSON.stringify(result), isError)
        );
        break;
      }
      // ====================================================================
      // Web search events
      // ====================================================================
      case "web_search_begin": {
        const ws = event;
        const callId = ws.call_id ?? `search-${this.turnIndex}`;
        events.push(
          this.createToolStart(callId, "WebSearch", {}, void 0, "Web Search")
        );
        this.toolIndex.append(callId, "WebSearch", {});
        break;
      }
      case "web_search_end": {
        const wsEnd = event;
        const callId = wsEnd.call_id ?? `search-${this.turnIndex}`;
        const result = wsEnd.query ?? "Search completed";
        events.push(
          this.createToolResult(callId, "WebSearch", result, false)
        );
        break;
      }
      // ====================================================================
      // Turn diff (file change summary)
      // ====================================================================
      case "turn_diff": {
        const diff = event;
        if (diff.unified_diff) {
          const filePaths = extractFilePathsFromDiff(diff.unified_diff);
          for (const fp of filePaths) {
            events.push(
              this.createToolStart(
                `diff-${fp}-${this.turnIndex}`,
                "Edit",
                { file_path: fp, unified_diff: diff.unified_diff },
                void 0,
                `Changed: ${fp}`
              )
            );
          }
        }
        break;
      }
      case "write_stdin": {
        const stdin = event;
        events.push({
          type: "status",
          message: stdin.content ? `Terminal input: ${stdin.content.slice(0, 80)}${stdin.content.length > 80 ? "..." : ""}` : "Terminal interaction"
        });
        break;
      }
      case "function_call_output": {
        const fco = event;
        const toolName = this.toolIndex.find(fco.call_id)?.name ?? "tool";
        events.push(
          this.createToolResult(fco.call_id, toolName, fco.output ?? "", fco.is_error ?? false)
        );
        this.toolIndex.markMatched(fco.call_id);
        break;
      }
      // ====================================================================
      // Lifecycle events
      // ====================================================================
      case "task_complete": {
        const tc = event;
        if (this.pendingAssistantText) {
          events.push({
            type: "text_complete",
            text: this.pendingAssistantText,
            isIntermediate: false,
            turnId: this.pendingAssistantTurnId || this.currentTurnId || void 0
          });
          this.pendingAssistantText = null;
        }
        events.push({ type: "complete" });
        break;
      }
      // ====================================================================
      // Ignored events (no UI value or handled elsewhere)
      // ====================================================================
      case "session_configured":
      case "task_started":
      case "token_count":
      case "user_message":
      // Filter synthetic, handle real user messages separately
      case "agent_message":
      // Full message, redundant with delta/complete
      case "conversation_path":
      case "background_event":
      case "turn_aborted":
        break;
      default:
        break;
    }
    return events;
  }
};
function extractTextFromContent(content) {
  if (!content) return null;
  let text = "";
  for (const block of content) {
    if (block.type === "text" && block.text) {
      text += block.text;
    }
  }
  return text || null;
}
function hasToolUseInContent(content) {
  if (!content) return false;
  return content.some((block) => block.type === "tool_use");
}
function extractToolUsesFromContent(content) {
  if (!content) return [];
  const result = [];
  for (const block of content) {
    if (block.type === "tool_use" && block.id && block.name) {
      result.push({ id: block.id, name: block.name, input: block.input ?? {} });
    }
  }
  return result;
}
function isSyntheticMessage(item) {
  const content = item.content;
  if (!content) return false;
  for (const block of content) {
    if (block.type === "text" && block.text) {
      if (block.text.startsWith("<environment>") || block.text.startsWith("<system-reminder>") || block.text.includes("is not available") && block.text.includes("Working directory")) {
        return true;
      }
    }
  }
  return false;
}
function decodeBase64Chunk(chunk) {
  if (!chunk) return null;
  try {
    return atob(chunk);
  } catch {
    return chunk;
  }
}
function stripShellEnvelope(output) {
  return output.replace(/^\[(stdout|stderr)\]\s*/i, "").replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "").trim();
}
function extractFilePathsFromDiff(diff) {
  const paths = [];
  for (const line of diff.split("\n")) {
    const match = line.match(/^diff --git\s+a\/(.+)\s+b\/(.+)/);
    if (match) {
      paths.push(match[2]);
    }
    const plusMatch = line.match(/^\+\+\+\s+b\/(.+)/);
    if (plusMatch && !paths.includes(plusMatch[1])) {
      paths.push(plusMatch[1]);
    }
  }
  return paths;
}
function parseCodexRolloutTrace(rolloutJsonl) {
  return new CodexRolloutAdapter().parseRollout(rolloutJsonl);
}

export {
  PushAgentEventStream,
  mapClaudeStreamJsonLine,
  mapCodexExecJsonLine,
  createLocalTimelineProjector,
  createFakeLocalAgentSession,
  generateTraceTurnId,
  generateTraceToolUseId,
  TraceToolIndex,
  parseTraceReadCommand,
  TraceEventAdapter,
  ClaudeStdoutAdapter,
  parseClaudeStdoutTrace,
  CodexRolloutAdapter,
  parseCodexRolloutTrace
};
