import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);

// src/adapters/claude/session/jsonl-hydration.ts
import { randomUUID } from "crypto";
import * as fs from "fs/promises";
import * as os from "os";
import * as path from "path";

// src/gateway-models.ts
var CACHE_TTL = 10 * 60 * 1e3;

// ../shared/dist/index.js
import { z } from "zod";
import { z as z2 } from "zod";
import { z as z3 } from "zod";
import { z as z4 } from "zod";
var ANALYTICS_EVENTS = {
  // App lifecycle
  APP_STARTED: "App started",
  APP_QUIT: "App quit",
  // Authentication
  USER_LOGGED_IN: "User logged in",
  USER_LOGGED_OUT: "User logged out",
  // Task management
  TASK_LIST_VIEWED: "Task list viewed",
  TASK_CREATED: "Task created",
  TASK_VIEWED: "Task viewed",
  TASK_RUN: "Task run",
  TASK_RUN_STARTED: "Task run started",
  TASK_RUN_COMPLETED: "Task run completed",
  TASK_RUN_CANCELLED: "Task run cancelled",
  TASK_RUN_STOPPED: "Task run stopped",
  PROMPT_SENT: "Prompt sent",
  // Claude Code session import
  CLAUDE_SESSIONS_SHOWN: "Claude Code sessions shown",
  CLAUDE_SESSION_IMPORTED: "Claude Code session imported",
  CLAUDE_SESSION_IMPORT_FAILED: "Claude Code session import failed",
  // Repository
  REPOSITORY_SELECTED: "Repository selected",
  // Git operations
  GIT_ACTION_EXECUTED: "Git action executed",
  PR_CREATED: "PR created",
  AGENT_FILE_ACTIVITY: "Agent file activity",
  BRANCH_LINKED: "Branch linked",
  BRANCH_UNLINKED: "Branch unlinked",
  BRANCH_LINK_DEFAULT_BRANCH_UNKNOWN: "Branch link default branch unknown",
  // File interactions
  FILE_OPENED: "File opened",
  FILE_DIFF_VIEWED: "File diff viewed",
  REVIEW_PANEL_VIEWED: "Review panel viewed",
  DIFF_VIEW_MODE_CHANGED: "Diff view mode changed",
  // Workspace events
  WORKSPACE_CREATED: "Workspace created",
  WORKSPACE_SCRIPTS_STARTED: "Workspace scripts started",
  FOLDER_REGISTERED: "Folder registered",
  // Navigation events
  SETTINGS_VIEWED: "Settings viewed",
  COMMAND_MENU_OPENED: "Command menu opened",
  COMMAND_MENU_ACTION: "Command menu action",
  COMMAND_CENTER_VIEWED: "Command center viewed",
  BRAINROT_ACTIVATED: "Brainrot activated",
  SKILL_BUTTON_TRIGGERED: "Skill button triggered",
  POSTHOG_WEB_OPENED: "PostHog web opened",
  // Permission events
  PERMISSION_RESPONDED: "Permission responded",
  PERMISSION_CANCELLED: "Permission cancelled",
  // Session config events
  SESSION_CONFIG_CHANGED: "Session config changed",
  // Settings events
  SETTING_CHANGED: "Setting changed",
  CUSTOM_SOUND_ADDED: "Custom sound added",
  CUSTOM_SOUND_RECORDING_SILENT: "Custom sound recording silent",
  // Feedback events
  TASK_FEEDBACK: "Task feedback",
  // Branch mismatch events
  BRANCH_MISMATCH_WARNING_SHOWN: "Branch mismatch warning shown",
  BRANCH_MISMATCH_ACTION: "Branch mismatch action",
  // Tour events
  TOUR_EVENT: "Tour event",
  // Onboarding events
  ONBOARDING_STARTED: "Onboarding started",
  ONBOARDING_STEP_VIEWED: "Onboarding step viewed",
  ONBOARDING_STEP_COMPLETED: "Onboarding step completed",
  ONBOARDING_STEP_SKIPPED: "Onboarding step skipped",
  ONBOARDING_SIGN_IN_INITIATED: "Onboarding sign in initiated",
  ONBOARDING_PROJECT_SELECTED: "Onboarding project selected",
  ONBOARDING_INVITE_CODE_SUBMITTED: "Onboarding invite code submitted",
  ONBOARDING_FOLDER_SELECTED: "Onboarding folder selected",
  ONBOARDING_GITHUB_CONNECT_STARTED: "Onboarding github connect started",
  ONBOARDING_GITHUB_CONNECT_FAILED: "Onboarding github connect failed",
  ONBOARDING_GITHUB_CONNECTED: "Onboarding github connected",
  ONBOARDING_CLI_CHECK_COMPLETED: "Onboarding cli check completed",
  ONBOARDING_CLI_RUN_COMPLETED: "Onboarding cli run completed",
  ONBOARDING_COMPLETED: "Onboarding completed",
  ONBOARDING_ABANDONED: "Onboarding abandoned",
  AI_CONSENT_GATE_SHOWN: "Ai consent gate shown",
  AI_CONSENT_APPROVED: "Ai consent approved",
  AI_CONSENT_GRANTED_INAPP: "Ai consent granted in-app",
  // Setup / onboarding events
  SETUP_DISCOVERY_STARTED: "Setup discovery started",
  SETUP_DISCOVERY_COMPLETED: "Setup discovery completed",
  SETUP_DISCOVERY_FAILED: "Setup discovery failed",
  SETUP_TASK_SELECTED: "Setup task selected",
  SETUP_TASK_DISMISSED: "Setup task dismissed",
  // Deep link events
  DEEP_LINK_NEW_TASK: "Deep link new task",
  DEEP_LINK_PLAN: "Deep link plan",
  DEEP_LINK_ISSUE: "Deep link issue",
  DEEP_LINK_ISSUE_FAILED: "Deep link issue failed",
  DEEP_LINK_CANVAS: "Deep link canvas",
  DEEP_LINK_CHANNEL: "Deep link channel",
  // Error events
  TASK_CREATION_FAILED: "Task creation failed",
  AGENT_SESSION_ERROR: "Agent session error",
  CLOUD_STREAM_DISCONNECTED: "Cloud stream disconnected",
  // Inbox events
  INBOX_VIEWED: "Inbox viewed",
  INBOX_REPORT_OPENED: "Inbox report opened",
  INBOX_REPORT_CLOSED: "Inbox report closed",
  INBOX_REPORT_ACTION: "Inbox report action",
  INBOX_REPORT_SCROLLED: "Inbox report scrolled",
  SIGNAL_SOURCE_CONNECTED: "Signal source connected",
  // Agents page events
  AGENTS_VIEWED: "Agents viewed",
  AGENTS_ACTION: "Agents action",
  // Scout events
  SCOUT_FLEET_VIEWED: "Scout fleet viewed",
  SCOUT_DETAIL_VIEWED: "Scout detail viewed",
  SCOUT_CONFIG_CHANGED: "Scout config changed",
  SCOUT_CHAT_STARTED: "Scout chat started",
  SCOUT_ACTION: "Scout action",
  // Usage and spend analysis events
  USAGE_VIEWED: "Usage viewed",
  SPEND_ANALYSIS_TASK_OPENED: "Spend analysis task opened",
  // Prompt history events
  PROMPT_HISTORY_OPENED: "Prompt history opened",
  PROMPT_HISTORY_SELECTED: "Prompt history selected",
  // Subscription events
  UPGRADE_PROMPT_SHOWN: "Upgrade prompt shown",
  UPGRADE_PROMPT_CLICKED: "Upgrade prompt clicked",
  CLOUD_TASK_USAGE_BLOCKED: "Cloud task usage blocked",
  SUBSCRIPTION_STARTED: "Subscription started",
  SUBSCRIPTION_CANCELLED: "Subscription cancelled",
  USAGE_BILLING_ANNOUNCEMENT_ACKNOWLEDGED: "Usage billing announcement acknowledged",
  // Project Bluebird (Channels) events
  CHANNELS_SPACE_VIEWED: "Channels space viewed",
  CHANNEL_ACTION: "Channel action",
  DASHBOARD_ACTION: "Dashboard action",
  CANVAS_PROMPT_SENT: "Canvas prompt sent",
  CONTEXT_ACTION: "Context action",
  // Autoresearch events
  AUTORESEARCH_ARMED: "Autoresearch armed",
  AUTORESEARCH_RUN_STARTED: "Autoresearch run started"
};
var INBOX_ANALYTICS_EVENT_NAMES = /* @__PURE__ */ new Set([
  ANALYTICS_EVENTS.INBOX_VIEWED,
  ANALYTICS_EVENTS.INBOX_REPORT_OPENED,
  ANALYTICS_EVENTS.INBOX_REPORT_CLOSED,
  ANALYTICS_EVENTS.INBOX_REPORT_ACTION,
  ANALYTICS_EVENTS.INBOX_REPORT_SCROLLED,
  ANALYTICS_EVENTS.SIGNAL_SOURCE_CONNECTED
]);
var archivedTaskSchema = z.object({
  taskId: z.string(),
  archivedAt: z.string(),
  folderId: z.string(),
  mode: z.enum(["worktree", "local", "cloud"]),
  worktreeName: z.string().nullable(),
  branchName: z.string().nullable(),
  checkpointId: z.string().nullable()
});
var IMAGE_MIME_TYPES = {
  png: "image/png",
  jpg: "image/jpeg",
  jpeg: "image/jpeg",
  gif: "image/gif",
  webp: "image/webp",
  bmp: "image/bmp",
  ico: "image/x-icon",
  tiff: "image/tiff",
  tif: "image/tiff",
  svg: "image/svg+xml",
  heic: "image/heic",
  heif: "image/heif",
  avif: "image/avif"
};
var IMAGE_EXTENSIONS = new Set(
  Object.keys(IMAGE_MIME_TYPES)
);
var MAX_DATA_URL_LENGTH = 20 * 1024 * 1024;
var MAX_IMAGE_BASE64_LENGTH = 15 * 1024 * 1024;
var MAX_CLAUDE_IMAGE_BYTES = 5 * 1024 * 1024;
var AUDIO_VIDEO_EXTENSIONS = /* @__PURE__ */ new Set([
  "mp3",
  "mp4",
  "wav",
  "avi",
  "mov",
  "mkv",
  "webm",
  "mpg",
  "mpeg",
  "flac",
  "ogg",
  "ogv",
  "m4a",
  "m4v",
  "aac"
]);
var ARCHIVE_EXTENSIONS = /* @__PURE__ */ new Set([
  "zip",
  "tar",
  "gz",
  "tgz",
  "bz2",
  "xz",
  "rar",
  "7z"
]);
var EXECUTABLE_EXTENSIONS = /* @__PURE__ */ new Set([
  "exe",
  "dll",
  "so",
  "dylib",
  "wasm",
  "bin",
  "o"
]);
var FONT_EXTENSIONS = /* @__PURE__ */ new Set([
  "ttf",
  "otf",
  "woff",
  "woff2",
  "eot"
]);
var DOCUMENT_BINARY_EXTENSIONS = /* @__PURE__ */ new Set(["pdf"]);
var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
  ...Object.keys(IMAGE_MIME_TYPES).filter((ext) => ext !== "svg"),
  ...AUDIO_VIDEO_EXTENSIONS,
  ...ARCHIVE_EXTENSIONS,
  ...EXECUTABLE_EXTENSIONS,
  ...FONT_EXTENSIONS,
  ...DOCUMENT_BINARY_EXTENSIONS
]);
var browserTabSchema = z2.object({
  id: z2.string(),
  windowId: z2.string(),
  /** Canvas this tab shows. Null for a task tab or a blank tab. */
  dashboardId: z2.string().nullable(),
  /** Task this tab shows. Null for a canvas tab or a blank tab. */
  taskId: z2.string().nullable().default(null),
  channelId: z2.string().nullable().default(null),
  /**
   * Channel sub-section this tab fronts (`artifacts` / `history` /
   * `context`). Null = the channel home, or a non-channel tab (canvas / task /
   * blank). Pairs with `channelId`: the two together identify a channel tab.
   */
  channelSection: z2.string().nullable().default(null),
  /**
   * Top-level app page this tab shows (`inbox` / `agents` / `skills` /
   * `mcp-servers` / `command-center` / `home`). Null for a canvas / task /
   * channel / blank tab. These pages have no channel, task, or dashboard id, so
   * this is what lets them be a real tab target (label + restore-on-refocus).
   */
  appView: z2.string().nullable().default(null),
  /** Gap-spaced ordering key within a window. Reindexed on collision. */
  position: z2.number(),
  /**
   * Reserved/unwired. Opaque per-tab state for future scroll restoration etc.
   * Plain `z.unknown()` (not `.default(null)`) so the inferred shape matches
   * the tRPC-wire inference on the client — keeps the renderer facade type and
   * the transport type identical.
   */
  scrollState: z2.unknown().optional(),
  createdAt: z2.number(),
  lastActiveAt: z2.number()
});
var windowBoundsSchema = z2.object({
  x: z2.number(),
  y: z2.number(),
  width: z2.number(),
  height: z2.number()
});
var browserWindowSchema = z2.object({
  id: z2.string(),
  isPrimary: z2.boolean(),
  /** Saved geometry for session restore. Null on web / before first persist. */
  bounds: windowBoundsSchema.nullable().default(null),
  /** Which tab is focused in this window. Null = channels landing. */
  activeTabId: z2.string().nullable().default(null)
});
var tabsSnapshotSchema = z2.object({
  windows: z2.array(browserWindowSchema),
  tabs: z2.array(browserTabSchema)
});
var prReviewCommentUserSchema = z3.object({
  login: z3.string(),
  avatar_url: z3.string()
});
var prReviewCommentSchema = z3.object({
  id: z3.number(),
  body: z3.string(),
  path: z3.string(),
  line: z3.number().nullable(),
  original_line: z3.number().nullable(),
  side: z3.enum(["LEFT", "RIGHT"]),
  start_line: z3.number().nullable(),
  start_side: z3.enum(["LEFT", "RIGHT"]).nullable(),
  diff_hunk: z3.string(),
  in_reply_to_id: z3.number().nullish(),
  user: prReviewCommentUserSchema,
  created_at: z3.string(),
  updated_at: z3.string(),
  subject_type: z3.enum(["line", "file"]).nullable()
});
var prReviewThreadSchema = z3.object({
  nodeId: z3.string(),
  isResolved: z3.boolean(),
  rootId: z3.number(),
  filePath: z3.string(),
  comments: z3.array(prReviewCommentSchema)
});
var githubRefKindSchema = z3.enum(["issue", "pr"]);
var githubRefStateSchema = z3.enum(["OPEN", "CLOSED", "MERGED"]);
var githubRefSchema = z3.object({
  kind: githubRefKindSchema,
  number: z3.number(),
  title: z3.string(),
  state: githubRefStateSchema,
  labels: z3.array(z3.string()),
  url: z3.string(),
  repo: z3.string(),
  isDraft: z3.boolean().optional()
});
var prActionTypeSchema = z3.enum(["close", "reopen", "ready", "draft"]);
var getPrInfoByUrlInput = z3.object({ prUrl: z3.string() });
var getPrInfoByUrlOutput = z3.object({
  number: z3.number(),
  title: z3.string(),
  body: z3.string(),
  author: z3.string().nullable(),
  state: z3.string(),
  merged: z3.boolean(),
  draft: z3.boolean(),
  /** GitHub computes mergeability asynchronously; null until it settles. */
  mergeable: z3.boolean().nullable(),
  /**
   * GitHub's `mergeable_state`: "clean" | "unstable" | "blocked" | "dirty" |
   * "behind" | "draft" | "unknown". "blocked" means branch protection forbids
   * the merge for this viewer — e.g. a required approving review is missing
   * (authors can't approve their own PRs) or required checks are failing.
   * Kept as a plain string so an undocumented value can't fail the parse.
   */
  mergeStateStatus: z3.string().catch("unknown"),
  baseRefName: z3.string().nullable(),
  headRefName: z3.string().nullable(),
  additions: z3.number(),
  deletions: z3.number(),
  changedFiles: z3.number()
});
var approvePrInput = z3.object({ prUrl: z3.string() });
var approvePrOutput = z3.object({
  success: z3.boolean(),
  message: z3.string()
});
var prMergeMethodSchema = z3.enum(["merge", "squash", "rebase"]);
var mergePrInput = z3.object({
  prUrl: z3.string(),
  method: prMergeMethodSchema
});
var mergePrOutput = z3.object({
  success: z3.boolean(),
  message: z3.string()
});
var prCheckBucketSchema = z3.enum([
  "fail",
  "cancel",
  "pending",
  "pass",
  "skipping"
]);
var prCheckSchema = z3.object({
  name: z3.string(),
  bucket: prCheckBucketSchema,
  link: z3.string().nullable(),
  workflow: z3.string().nullable(),
  description: z3.string().nullable()
});
var getPrChecksInput = z3.object({ prUrl: z3.string() });
var getPrChecksOutput = z3.array(prCheckSchema).nullable();
var prConversationCommentSchema = z3.object({
  id: z3.number(),
  author: z3.string(),
  avatarUrl: z3.string().nullable(),
  body: z3.string(),
  createdAt: z3.string(),
  url: z3.string().nullable()
});
var getPrCommentsInput = z3.object({ prUrl: z3.string() });
var getPrCommentsOutput = z3.array(prConversationCommentSchema).nullable();
var TOKEN_REFRESH_BUFFER_MS = 30 * 60 * 1e3;
var TOKEN_REFRESH_FORCE_MS = 60 * 1e3;
var consoleLogger = {
  info: (_message, _data) => {
  },
  debug: (_message, _data) => {
  },
  error: (_message, _data) => {
  },
  warn: (_message, _data) => {
  }
};
var Saga = class {
  completedSteps = [];
  currentStepName = "unknown";
  stepTimings = [];
  log;
  constructor(logger) {
    this.log = logger ?? consoleLogger;
  }
  /**
   * Run the saga with the given input.
   * Returns a discriminated union result - either success with data or failure with error details.
   */
  async run(input) {
    this.completedSteps = [];
    this.currentStepName = "unknown";
    this.stepTimings = [];
    const sagaStart = performance.now();
    try {
      const result = await this.execute(input);
      const totalDuration = performance.now() - sagaStart;
      this.log.debug("Saga completed successfully", {
        sagaName: this.sagaName,
        stepsCompleted: this.completedSteps.length,
        totalDurationMs: Math.round(totalDuration),
        stepTimings: this.stepTimings
      });
      return { success: true, data: result };
    } catch (error) {
      this.log.error("Saga failed, initiating rollback", {
        sagaName: this.sagaName,
        failedStep: this.currentStepName,
        error: error instanceof Error ? error.message : String(error),
        completedStepTimings: this.stepTimings
      });
      await this.rollback();
      return {
        success: false,
        error: error instanceof Error ? error.message : String(error),
        failedStep: this.currentStepName
      };
    }
  }
  /**
   * Execute a step with its rollback action.
   * If the step succeeds, its rollback action is stored for potential rollback.
   * The step name is automatically tracked for error reporting.
   *
   * @param config - Step configuration with name, execute, and rollback functions
   * @returns The result of the execute function
   * @throws Re-throws any error from the execute function (triggers rollback)
   */
  async step(config) {
    this.currentStepName = config.name;
    const stepStart = performance.now();
    const result = await config.execute();
    const durationMs = Math.round(performance.now() - stepStart);
    this.stepTimings.push({ name: config.name, durationMs });
    this.completedSteps.push({
      name: config.name,
      rollback: () => config.rollback(result)
    });
    return result;
  }
  /**
   * Execute a step that doesn't need rollback.
   * Useful for read-only operations or operations that are idempotent.
   * The step name is automatically tracked for error reporting.
   *
   * @param name - Step name for logging and error tracking
   * @param execute - The action to execute
   * @returns The result of the execute function
   */
  async readOnlyStep(name, execute) {
    this.currentStepName = name;
    const stepStart = performance.now();
    const result = await execute();
    const durationMs = Math.round(performance.now() - stepStart);
    this.stepTimings.push({ name, durationMs });
    return result;
  }
  /**
   * Roll back all completed steps in reverse order.
   * Rollback errors are logged but don't stop the rollback of other steps.
   */
  async rollback() {
    this.log.info("Rolling back saga", {
      stepsToRollback: this.completedSteps.length
    });
    const stepsReversed = [...this.completedSteps].reverse();
    for (const step of stepsReversed) {
      try {
        await step.rollback();
      } catch (error) {
        this.log.error(`Failed to rollback step: ${step.name}`, {
          error: error instanceof Error ? error.message : String(error)
        });
      }
    }
    this.log.info("Rollback completed", {
      stepsAttempted: this.completedSteps.length
    });
  }
  /**
   * Get the number of completed steps (useful for testing)
   */
  getCompletedStepCount() {
    return this.completedSteps.length;
  }
};
var VIDEO_MIME_TYPES = {
  mp4: "video/mp4",
  m4v: "video/mp4",
  mov: "video/quicktime",
  webm: "video/webm",
  ogv: "video/ogg"
};
var PLAYABLE_VIDEO_EXTENSIONS = new Set(
  Object.keys(VIDEO_MIME_TYPES)
);
var ALLOWED_VIDEO_MIME_TYPES = new Set(
  Object.values(VIDEO_MIME_TYPES)
);
var MAX_VIDEO_BASE64_LENGTH = 50 * 1024 * 1024;
var workspaceModeSchema = z4.enum(["worktree", "local", "cloud", "root"]).transform((val) => val === "root" ? "local" : val);
var worktreeInfoSchema = z4.object({
  worktreePath: z4.string(),
  worktreeName: z4.string(),
  branchName: z4.string().nullable(),
  baseBranch: z4.string(),
  createdAt: z4.string(),
  output: z4.string().optional()
});
var workspaceInfoSchema = z4.object({
  taskId: z4.string(),
  mode: workspaceModeSchema,
  worktree: worktreeInfoSchema.nullable(),
  branchName: z4.string().nullable(),
  linkedBranch: z4.string().nullable()
});
var workspaceSchema = z4.object({
  taskId: z4.string(),
  folderId: z4.string(),
  folderPath: z4.string(),
  mode: workspaceModeSchema,
  worktreePath: z4.string().nullable(),
  worktreeName: z4.string().nullable(),
  branchName: z4.string().nullable(),
  baseBranch: z4.string().nullable(),
  linkedBranch: z4.string().nullable(),
  createdAt: z4.string(),
  /**
   * Synthetic workspace for a repo-less channel task: its folderPath is a
   * scratch dir, not a registered folder. Marks it so callers (e.g. the
   * navigation task binder) don't try to register it as a folder or git-init it.
   */
  isScratch: z4.boolean().optional()
});

// src/adapters/claude/session/jsonl-hydration.ts
var CHARS_PER_TOKEN = 3;
var DEFAULT_MAX_TOKENS = 8e4;
function estimateTurnTokens(turn) {
  let chars = 0;
  for (const block of turn.content) {
    if ("text" in block && typeof block.text === "string") {
      chars += block.text.length;
    }
  }
  if (turn.toolCalls) {
    for (const tc of turn.toolCalls) {
      chars += JSON.stringify(tc.input ?? "").length;
      if (tc.result !== void 0) {
        chars += typeof tc.result === "string" ? tc.result.length : JSON.stringify(tc.result).length;
      }
    }
  }
  return Math.ceil(chars / CHARS_PER_TOKEN);
}
function selectRecentTurns(turns, maxTokens = DEFAULT_MAX_TOKENS) {
  let budget = maxTokens;
  let startIndex = turns.length;
  for (let i = turns.length - 1; i >= 0; i--) {
    const cost = estimateTurnTokens(turns[i]);
    if (cost > budget) break;
    budget -= cost;
    startIndex = i;
  }
  if (startIndex === turns.length && turns.length > 0) {
    return selectOversizedTailFallback(turns, maxTokens);
  }
  while (startIndex < turns.length && turns[startIndex].role !== "user") {
    startIndex++;
  }
  return turns.slice(startIndex);
}
function selectOversizedTailFallback(turns, maxTokens) {
  const last = turns[turns.length - 1];
  let userIndex = turns.length - 1;
  while (userIndex >= 0 && turns[userIndex].role !== "user") {
    userIndex--;
  }
  const selected = [];
  let budget = maxTokens;
  if (userIndex >= 0) {
    selected.push(turns[userIndex]);
    budget -= estimateTurnTokens(turns[userIndex]);
  }
  if (userIndex !== turns.length - 1) {
    selected.push(dropOldestToolCalls(last, Math.max(budget, 0)));
  }
  return selected;
}
function dropOldestToolCalls(turn, budget) {
  if (!turn.toolCalls?.length) return turn;
  const toolCalls = [...turn.toolCalls];
  const trimmed = { ...turn, toolCalls };
  while (toolCalls.length > 0 && estimateTurnTokens(trimmed) > budget) {
    toolCalls.shift();
  }
  if (toolCalls.length === 0) {
    trimmed.toolCalls = void 0;
  }
  return trimmed;
}

// src/acp-extensions.ts
var POSTHOG_NOTIFICATIONS = {
  /** Git branch was created for a task */
  BRANCH_CREATED: "_posthog/branch_created",
  /** Task run has started execution */
  RUN_STARTED: "_posthog/run_started",
  /** Task has completed (success or failure) */
  TASK_COMPLETE: "_posthog/task_complete",
  /** Agent finished processing a turn (prompt returned, waiting for next input) */
  TURN_COMPLETE: "_posthog/turn_complete",
  /** Background/task-notification-triggered reply finished. Same rendering
   * effect as TURN_COMPLETE (closes out the current turn) without touching
   * the tracked prompt lifecycle that TURN_COMPLETE drives on the agent side. */
  BACKGROUND_TURN_COMPLETE: "_posthog/background_turn_complete",
  /** Error occurred during task execution */
  ERROR: "_posthog/error",
  /** Console/log output from the agent */
  CONSOLE: "_posthog/console",
  /** Maps taskRunId to agent's sessionId and adapter type (for resumption) */
  SDK_SESSION: "_posthog/sdk_session",
  /** Git checkpoint captured for handoff */
  GIT_CHECKPOINT: "_posthog/git_checkpoint",
  /** Agent mode changed (interactive/background) */
  MODE_CHANGE: "_posthog/mode_change",
  /** Request to resume a session from previous state */
  SESSION_RESUME: "_posthog/session/resume",
  /** User message sent from client to agent */
  USER_MESSAGE: "_posthog/user_message",
  /** Request to cancel current operation */
  CANCEL: "_posthog/cancel",
  /** Request to close the session */
  CLOSE: "_posthog/close",
  /** Agent status update (thinking, working, etc.) */
  STATUS: "_posthog/status",
  /** Structured backend progress notification; events in the same turn group into one card on the client */
  PROGRESS: "_posthog/progress",
  /** Task-level notification (progress, milestones) */
  TASK_NOTIFICATION: "_posthog/task_notification",
  /** Marks a boundary for log compaction */
  COMPACT_BOUNDARY: "_posthog/compact_boundary",
  /** Token usage update for a session turn */
  USAGE_UPDATE: "_posthog/usage_update",
  /** PostHog products used during a turn (derived from MCP exec calls) */
  RESOURCES_USED: "_posthog/resources_used",
  /** Response to a relayed permission request (plan approval, question) */
  PERMISSION_RESPONSE: "_posthog/permission_response",
  /** Permission request raised by the agent, persisted to the log so a reconnecting client can recover its requestId */
  PERMISSION_REQUEST: "_posthog/permission_request",
  /** Permission request resolved, persisted so a reconnecting client can tell it is no longer pending */
  PERMISSION_RESOLVED: "_posthog/permission_resolved",
  /** RTK output-compression token savings tallied at the end of a run */
  RTK_SAVINGS: "_posthog/rtk_savings",
  /** Latest native Codex goal state, persisted so cold cloud resumes can restore it. */
  CODEX_GOAL: "_posthog/codex_goal",
  /** Desktop → sandbox reply to an MCP relay request (docs/cloud-mcp-relay.md). */
  MCP_RESPONSE: "_posthog/mcp_response"
};

// src/sagas/resume-saga.ts
var ResumeSaga = class extends Saga {
  sagaName = "ResumeSaga";
  async execute(input) {
    const { taskId, runId, apiClient } = input;
    const taskRun = await this.readOnlyStep(
      "fetch_task_run",
      () => apiClient.getTaskRun(taskId, runId)
    );
    if (!taskRun.log_url) {
      this.log.info("No log URL found, starting fresh");
      return this.emptyResult();
    }
    const entries = await this.readOnlyStep(
      "fetch_logs",
      () => apiClient.fetchTaskRunLogs(taskRun)
    );
    if (entries.length === 0) {
      this.log.info("No log entries found, starting fresh");
      return this.emptyResult();
    }
    this.log.info("Fetched log entries", { count: entries.length });
    const latestGitCheckpoint = await this.readOnlyStep(
      "find_git_checkpoint",
      () => Promise.resolve(this.findLatestGitCheckpoint(entries))
    );
    if (latestGitCheckpoint) {
      this.log.info("Found git checkpoint", {
        checkpointId: latestGitCheckpoint.checkpointId,
        branch: latestGitCheckpoint.branch
      });
    }
    const conversation = await this.readOnlyStep(
      "rebuild_conversation",
      () => Promise.resolve(this.rebuildConversation(entries))
    );
    const lastDevice = await this.readOnlyStep(
      "find_device",
      () => Promise.resolve(this.findLastDeviceInfo(entries))
    );
    const sessionId = await this.readOnlyStep(
      "find_session_id",
      () => Promise.resolve(this.findSessionId(entries))
    );
    const nativeGoal = await this.readOnlyStep(
      "find_native_goal",
      () => Promise.resolve(this.findNativeGoal(entries))
    );
    this.log.info("Resume state rebuilt", {
      turns: conversation.length,
      hasGitCheckpoint: !!latestGitCheckpoint,
      hasSessionId: !!sessionId,
      interrupted: false
    });
    return {
      conversation,
      latestGitCheckpoint,
      interrupted: false,
      lastDevice,
      logEntryCount: entries.length,
      sessionId,
      nativeGoal
    };
  }
  emptyResult() {
    return {
      conversation: [],
      latestGitCheckpoint: null,
      interrupted: false,
      logEntryCount: 0,
      sessionId: null,
      nativeGoal: void 0
    };
  }
  findNativeGoal(entries) {
    const statuses = /* @__PURE__ */ new Set([
      "active",
      "paused",
      "blocked",
      "usageLimited",
      "budgetLimited",
      "complete"
    ]);
    const methods = /* @__PURE__ */ new Set([
      POSTHOG_NOTIFICATIONS.CODEX_GOAL,
      `_${POSTHOG_NOTIFICATIONS.CODEX_GOAL}`
    ]);
    for (let index = entries.length - 1; index >= 0; index--) {
      const notification = entries[index].notification;
      if (!methods.has(notification?.method ?? "")) continue;
      const goal = notification?.params?.goal;
      if (goal === null) return null;
      if (!goal || typeof goal !== "object") continue;
      const value = goal;
      if (typeof value.objective === "string" && typeof value.status === "string" && statuses.has(value.status)) {
        return {
          objective: value.objective,
          status: value.status
        };
      }
    }
    return void 0;
  }
  findSessionId(entries) {
    const runStarted = POSTHOG_NOTIFICATIONS.RUN_STARTED;
    for (let i = entries.length - 1; i >= 0; i--) {
      const method = entries[i].notification?.method;
      if (method === runStarted || method === `_${runStarted}`) {
        const params = entries[i].notification?.params;
        if (typeof params?.sessionId === "string" && params.sessionId) {
          return params.sessionId;
        }
      }
    }
    return null;
  }
  findLatestGitCheckpoint(entries) {
    const sdkPrefixedMethod = `_${POSTHOG_NOTIFICATIONS.GIT_CHECKPOINT}`;
    for (let i = entries.length - 1; i >= 0; i--) {
      const entry = entries[i];
      const method = entry.notification?.method;
      if (method === sdkPrefixedMethod || method === POSTHOG_NOTIFICATIONS.GIT_CHECKPOINT) {
        const params = entry.notification?.params;
        if (params?.checkpointId && params?.checkpointRef) {
          return params;
        }
      }
    }
    return null;
  }
  findLastDeviceInfo(entries) {
    for (let i = entries.length - 1; i >= 0; i--) {
      const entry = entries[i];
      const params = entry.notification?.params;
      if (params?.device) {
        return params.device;
      }
    }
    return void 0;
  }
  rebuildConversation(entries) {
    const turns = [];
    let currentAssistantContent = [];
    let currentToolCalls = [];
    for (const entry of entries) {
      const method = entry.notification?.method;
      const params = entry.notification?.params;
      if (method === "session/update" && params?.update) {
        const update = params.update;
        const sessionUpdate = update.sessionUpdate;
        switch (sessionUpdate) {
          case "user_message":
          case "user_message_chunk": {
            if (currentAssistantContent.length > 0 || currentToolCalls.length > 0) {
              turns.push({
                role: "assistant",
                content: currentAssistantContent,
                toolCalls: currentToolCalls.length > 0 ? currentToolCalls : void 0
              });
              currentAssistantContent = [];
              currentToolCalls = [];
            }
            const content = update.content;
            const contentArray = Array.isArray(content) ? content : [content];
            turns.push({
              role: "user",
              content: contentArray
            });
            break;
          }
          case "agent_message": {
            const content = update.content;
            if (content) {
              if (content.type === "text" && currentAssistantContent.length > 0 && currentAssistantContent[currentAssistantContent.length - 1].type === "text") {
                const lastBlock = currentAssistantContent[currentAssistantContent.length - 1];
                lastBlock.text += content.text;
              } else {
                currentAssistantContent.push(content);
              }
            }
            break;
          }
          case "agent_message_chunk": {
            const content = update.content;
            if (content) {
              if (content.type === "text" && currentAssistantContent.length > 0 && currentAssistantContent[currentAssistantContent.length - 1].type === "text") {
                const lastBlock = currentAssistantContent[currentAssistantContent.length - 1];
                lastBlock.text += content.text;
              } else {
                currentAssistantContent.push(content);
              }
            }
            break;
          }
          case "tool_call":
          case "tool_call_update": {
            const meta = update._meta?.claudeCode;
            if (meta) {
              const toolCallId = meta.toolCallId;
              const toolName = meta.toolName;
              const toolInput = meta.toolInput;
              const toolResponse = meta.toolResponse;
              if (toolCallId && toolName) {
                let toolCall = currentToolCalls.find(
                  (tc) => tc.toolCallId === toolCallId
                );
                if (!toolCall) {
                  toolCall = {
                    toolCallId,
                    toolName,
                    input: toolInput
                  };
                  currentToolCalls.push(toolCall);
                }
                if (toolResponse !== void 0) {
                  toolCall.result = toolResponse;
                }
              }
            }
            break;
          }
          case "tool_result": {
            const meta = update._meta?.claudeCode;
            if (meta) {
              const toolCallId = meta.toolCallId;
              const toolResponse = meta.toolResponse;
              if (toolCallId) {
                const toolCall = currentToolCalls.find(
                  (tc) => tc.toolCallId === toolCallId
                );
                if (toolCall && toolResponse !== void 0) {
                  toolCall.result = toolResponse;
                }
              }
            }
            break;
          }
        }
      }
    }
    if (currentAssistantContent.length > 0 || currentToolCalls.length > 0) {
      turns.push({
        role: "assistant",
        content: currentAssistantContent,
        toolCalls: currentToolCalls.length > 0 ? currentToolCalls : void 0
      });
    }
    return turns;
  }
};

// src/utils/logger.ts
var Logger = class _Logger {
  debugEnabled;
  prefix;
  scope;
  onLog;
  constructor(config = {}) {
    this.debugEnabled = config.debug ?? false;
    this.prefix = config.prefix ?? "[PostHog Agent]";
    this.scope = config.scope ?? "agent";
    this.onLog = config.onLog;
  }
  formatMessage(level, message, data) {
    const timestamp = (/* @__PURE__ */ new Date()).toISOString();
    const base = `${timestamp} ${this.prefix} [${level}] ${message}`;
    if (data !== void 0) {
      return `${base} ${JSON.stringify(data, null, 2)}`;
    }
    return base;
  }
  emitLog(level, message, data) {
    if (this.onLog) {
      this.onLog(level, this.scope, message, data);
      return;
    }
    const shouldLog = this.debugEnabled || level === "error";
    if (shouldLog) {
      console[level](this.formatMessage(level.toLowerCase(), message, data));
    }
  }
  error(message, error) {
    const data = error instanceof Error ? { message: error.message, stack: error.stack } : error;
    this.emitLog("error", message, data);
  }
  warn(message, data) {
    this.emitLog("warn", message, data);
  }
  info(message, data) {
    this.emitLog("info", message, data);
  }
  debug(message, data) {
    this.emitLog("debug", message, data);
  }
  child(childPrefix) {
    return new _Logger({
      debug: this.debugEnabled,
      prefix: `${this.prefix} [${childPrefix}]`,
      scope: `${this.scope}:${childPrefix}`,
      onLog: this.onLog
    });
  }
};

// src/resume.ts
async function resumeFromLog(config) {
  const logger = config.logger || new Logger({ debug: false, prefix: "[Resume]" });
  logger.info("Resuming from log", {
    taskId: config.taskId,
    runId: config.runId
  });
  const saga = new ResumeSaga(logger);
  const result = await saga.run({
    taskId: config.taskId,
    runId: config.runId,
    repositoryPath: config.repositoryPath,
    apiClient: config.apiClient,
    logger
  });
  if (!result.success) {
    logger.error("Failed to resume from log", {
      error: result.error,
      failedStep: result.failedStep
    });
    throw new Error(
      `Failed to resume at step '${result.failedStep}': ${result.error}`
    );
  }
  return {
    conversation: result.data.conversation,
    latestGitCheckpoint: result.data.latestGitCheckpoint,
    interrupted: result.data.interrupted,
    lastDevice: result.data.lastDevice,
    logEntryCount: result.data.logEntryCount,
    sessionId: result.data.sessionId,
    nativeGoal: result.data.nativeGoal
  };
}
function conversationToPromptHistory(conversation) {
  return conversation.map((turn) => ({
    role: turn.role,
    content: turn.content
  }));
}
var RESUME_HISTORY_TOKEN_BUDGET = 5e4;
var TOOL_RESULT_MAX_CHARS = 2e3;
var RESUME_CONTEXT_MARKERS = [
  "You are resuming a previous conversation",
  "Here is the conversation history from the",
  "Continue from where you left off"
];
function isResumeContextTurn(turn) {
  if (turn.role !== "user") return false;
  const text = turn.content.filter((b) => b.type === "text").map((b) => b.text).join("");
  return RESUME_CONTEXT_MARKERS.some((marker) => text.includes(marker));
}
function formatConversationForResume(conversation) {
  const filtered = conversation.filter((turn) => !isResumeContextTurn(turn));
  const selected = selectRecentTurns(filtered, RESUME_HISTORY_TOKEN_BUDGET);
  const parts = [];
  if (selected.length < filtered.length) {
    parts.push(
      `*(${filtered.length - selected.length} earlier turns omitted)*`
    );
  }
  for (const turn of selected) {
    const role = turn.role === "user" ? "User" : "Assistant";
    const textParts = turn.content.filter((block) => block.type === "text").map((block) => block.text);
    if (textParts.length > 0) {
      parts.push(`**${role}**: ${textParts.join("\n")}`);
    }
    if (turn.toolCalls?.length) {
      const toolSummary = turn.toolCalls.map((tc) => {
        let resultStr = "";
        if (tc.result !== void 0) {
          const raw = typeof tc.result === "string" ? tc.result : JSON.stringify(tc.result);
          resultStr = raw.length > TOOL_RESULT_MAX_CHARS ? ` \u2192 ${raw.substring(0, TOOL_RESULT_MAX_CHARS)}...(truncated)` : ` \u2192 ${raw}`;
        }
        return `  - ${tc.toolName}${resultStr}`;
      }).join("\n");
      parts.push(`**${role} (tools)**:
${toolSummary}`);
    }
  }
  return parts.join("\n\n");
}
export {
  conversationToPromptHistory,
  formatConversationForResume,
  resumeFromLog
};
//# sourceMappingURL=resume.js.map