// src/lib/api-client/sessions.ts
import {
  createSession as apiCreateSession,
  listSessions as apiListSessions,
  listMessages as apiListMessages,
  createMessage as apiCreateMessage,
  abortSession as apiAbortSession,
  deleteSession as apiDeleteSession,
  markSessionViewed as apiMarkSessionViewed,
  updateSession as apiUpdateSession,
  getSessionQueue as apiGetSessionQueue,
  removeFromQueue as apiRemoveFromQueue,
  retryMessage as apiRetryMessage,
  buildSessionStreamUrl
} from "@ottocode/api";

// src/lib/api-client/utils.ts
import { client } from "@ottocode/api";

// src/lib/platform.ts
function getPlatformWindow() {
  if (typeof window === "undefined")
    return null;
  return window;
}
function openPlatformUrl(url) {
  const win = getPlatformWindow();
  if (!win?.OTTO_OPEN_URL)
    return false;
  win.OTTO_OPEN_URL(url);
  return true;
}
function showPlatformNotification(notification) {
  const win = getPlatformWindow();
  if (!win?.OTTO_SHOW_NOTIFICATION)
    return false;
  win.OTTO_SHOW_NOTIFICATION(notification);
  return true;
}
function listPlatformSystemFonts() {
  const win = getPlatformWindow();
  if (!win?.OTTO_LIST_SYSTEM_FONTS)
    return null;
  return win.OTTO_LIST_SYSTEM_FONTS();
}
function notifyPlatformFontFamilyChanged(fontFamily) {
  const win = getPlatformWindow();
  if (!win?.OTTO_SET_DESKTOP_FONT)
    return false;
  win.OTTO_SET_DESKTOP_FONT(fontFamily);
  return true;
}
function openPlatformSession(sessionId) {
  const win = getPlatformWindow();
  if (!win?.OTTO_OPEN_SESSION)
    return false;
  win.OTTO_OPEN_SESSION(sessionId);
  return true;
}
function getPlatformWindowFocused() {
  const win = getPlatformWindow();
  if (!win?.OTTO_IS_WINDOW_FOCUSED)
    return null;
  return win.OTTO_IS_WINDOW_FOCUSED();
}
function hasPlatformOpenUrl() {
  return !!getPlatformWindow()?.OTTO_OPEN_URL;
}
function hasPlatformSystemFonts() {
  return !!getPlatformWindow()?.OTTO_LIST_SYSTEM_FONTS;
}
function isPlatformDesktop() {
  if (typeof window === "undefined")
    return false;
  try {
    return "__TAURI__" in window || "__TAURI_INTERNALS__" in window || "__TAURI_METADATA__" in window;
  } catch {
    return false;
  }
}

// src/lib/config.ts
var RUNTIME_API_BASE_URL_STORAGE_KEY = "otto-api-base-url";
function normalizeApiBaseUrl(value) {
  const trimmed = value.trim();
  if (!trimmed) {
    throw new Error("Enter an otto tunnel URL.");
  }
  let url;
  try {
    url = new URL(trimmed);
  } catch {
    throw new Error("Enter a valid URL, including http:// or https://.");
  }
  if (url.protocol !== "http:" && url.protocol !== "https:") {
    throw new Error("Tunnel URL must start with http:// or https://.");
  }
  url.hash = "";
  url.pathname = url.pathname.replace(/\/+$/, "") || "";
  return url.toString().replace(/\/+$/, "");
}
function getStoredApiBaseUrl() {
  if (typeof window === "undefined")
    return;
  if (isPlatformDesktop())
    return;
  try {
    return window.localStorage.getItem(RUNTIME_API_BASE_URL_STORAGE_KEY) ?? undefined;
  } catch {
    return;
  }
}
function getConfiguredRuntimeApiBaseUrl() {
  if (typeof window === "undefined")
    return;
  const params = new URLSearchParams(window.location.search);
  const urlParam = params.get("url");
  if (urlParam)
    return normalizeApiBaseUrl(urlParam);
  const win = window;
  if (win.OTTO_SERVER_URL)
    return normalizeApiBaseUrl(win.OTTO_SERVER_URL);
  if (win.__OTTO_API_URL__)
    return normalizeApiBaseUrl(win.__OTTO_API_URL__);
  const storedUrl = getStoredApiBaseUrl();
  if (storedUrl)
    return normalizeApiBaseUrl(storedUrl);
  return;
}
function hasConfiguredRuntimeApiBaseUrl() {
  return Boolean(getConfiguredRuntimeApiBaseUrl());
}
function setRuntimeApiBaseUrl(value) {
  const baseUrl = normalizeApiBaseUrl(value);
  if (typeof window !== "undefined") {
    const win = window;
    win.OTTO_SERVER_URL = baseUrl;
    if (!isPlatformDesktop()) {
      try {
        window.localStorage.setItem(RUNTIME_API_BASE_URL_STORAGE_KEY, baseUrl);
      } catch {}
    }
  }
  return baseUrl;
}
function clearRuntimeApiBaseUrl() {
  if (typeof window === "undefined")
    return;
  const win = window;
  delete win.OTTO_SERVER_URL;
  delete win.__OTTO_API_URL__;
  try {
    window.localStorage.removeItem(RUNTIME_API_BASE_URL_STORAGE_KEY);
  } catch {}
}
function computeApiBaseUrl() {
  const runtimeUrl = getConfiguredRuntimeApiBaseUrl();
  if (runtimeUrl) {
    return runtimeUrl;
  }
  const envUrl = import.meta.env?.VITE_API_BASE_URL;
  if (envUrl)
    return normalizeApiBaseUrl(envUrl);
  return "http://localhost:9100";
}
function getRuntimeApiBaseUrl() {
  return computeApiBaseUrl();
}
var API_BASE_URL = computeApiBaseUrl();
var config = {
  apiBaseUrl: API_BASE_URL
};

// src/lib/api-client/utils.ts
function getClientAdapter() {
  if (typeof window !== "undefined" && typeof window.fetch === "function") {
    return "fetch";
  }
  return;
}
function extractErrorMessage(error) {
  if (!error)
    return "Unknown error";
  if (typeof error === "string")
    return error;
  if (error && typeof error === "object") {
    const errObj = error;
    if (errObj.error && typeof errObj.error === "object") {
      const innerError = errObj.error;
      if (typeof innerError.message === "string")
        return innerError.message;
    }
    if (typeof errObj.error === "string")
      return errObj.error;
    if (typeof errObj.message === "string")
      return errObj.message;
    try {
      return JSON.stringify(error);
    } catch {
      return "Error occurred (unable to parse)";
    }
  }
  return "Unknown error";
}
function configureApiClient() {
  const baseURL = getRuntimeApiBaseUrl();
  client.setConfig({
    baseURL,
    adapter: getClientAdapter()
  });
}
configureApiClient();
function getBaseUrl() {
  return getRuntimeApiBaseUrl();
}
function convertSession(apiSession) {
  return {
    ...apiSession,
    title: apiSession.title ?? null,
    createdAt: typeof apiSession.createdAt === "string" ? new Date(apiSession.createdAt).getTime() : apiSession.createdAt,
    lastActiveAt: typeof apiSession.lastActiveAt === "string" ? new Date(apiSession.lastActiveAt).getTime() : apiSession.lastActiveAt,
    lastViewedAt: typeof apiSession.lastViewedAt === "string" ? new Date(apiSession.lastViewedAt).getTime() : apiSession.lastViewedAt
  };
}
function convertMessage(apiMessage) {
  return {
    ...apiMessage,
    createdAt: typeof apiMessage.createdAt === "string" ? new Date(apiMessage.createdAt).getTime() : apiMessage.createdAt,
    completedAt: apiMessage.completedAt ? typeof apiMessage.completedAt === "string" ? new Date(apiMessage.completedAt).getTime() : apiMessage.completedAt : null
  };
}

// src/lib/api-client/sessions.ts
var sessionsMixin = {
  async getSessions() {
    const page = await this.getSessionsPage({ limit: 200 });
    return page.items;
  },
  async getSessionsPage(params = {}) {
    const { limit = 50, offset = 0 } = params;
    const response = await apiListSessions({
      query: { limit, offset }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    const data = response.data;
    return {
      items: (data?.items ?? []).map((s) => convertSession(s)),
      hasMore: data?.hasMore ?? false,
      nextOffset: data?.nextOffset ?? null
    };
  },
  async createSession(data) {
    const response = await apiCreateSession({
      body: data
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    if (!response.data)
      throw new Error("No data returned from create session");
    return convertSession(response.data);
  },
  async updateSession(sessionId, data) {
    const response = await apiUpdateSession({
      path: { sessionId },
      body: data
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return convertSession(response.data);
  },
  async markSessionViewed(sessionId) {
    const response = await apiMarkSessionViewed({ path: { sessionId } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return convertSession(response.data);
  },
  async deleteSession(sessionId) {
    const response = await apiDeleteSession({ path: { sessionId } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async createHandoff(sessionId) {
    const response = await fetch(`${getBaseUrl()}/v1/sessions/${encodeURIComponent(sessionId)}/handoff`, { method: "POST" });
    const data = await response.json().catch(() => null);
    if (!response.ok)
      throw new Error(extractErrorMessage(data));
    if (!data?.session || !data?.sessionId) {
      throw new Error("No data returned from handoff");
    }
    return {
      session: convertSession(data.session),
      sessionId: String(data.sessionId),
      sourceSessionId: String(data.sourceSessionId),
      message: String(data.message ?? "")
    };
  },
  async abortSession(sessionId) {
    const response = await apiAbortSession({ path: { sessionId } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async abortMessage(sessionId, _messageId) {
    const response = await apiAbortSession({
      path: { sessionId }
    });
    if (response.error)
      throw new Error("Failed to abort message");
    return response.data;
  },
  async getQueueState(sessionId) {
    const response = await apiGetSessionQueue({ path: { sessionId } });
    if (response.error)
      throw new Error("Failed to get queue state");
    return response.data;
  },
  async removeFromQueue(sessionId, messageId) {
    const response = await apiRemoveFromQueue({
      path: { sessionId, messageId }
    });
    if (response.error)
      throw new Error("Failed to remove from queue");
    return response.data;
  },
  async sendQueuedMessageNow(sessionId, messageId) {
    const response = await fetch(`${getBaseUrl()}/v1/sessions/${encodeURIComponent(sessionId)}/queue/${encodeURIComponent(messageId)}/send-now`, { method: "POST" });
    const data = await response.json().catch(() => null);
    if (!response.ok)
      throw new Error(extractErrorMessage(data));
    return data;
  },
  async getMessages(sessionId) {
    const response = await apiListMessages({ path: { id: sessionId } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return (response.data || []).map(convertMessage);
  },
  async sendMessage(sessionId, data) {
    const response = await apiCreateMessage({
      path: { id: sessionId },
      body: data
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  getStreamUrl(sessionId) {
    return buildSessionStreamUrl({ baseUrl: getBaseUrl(), sessionId });
  },
  async retryMessage(sessionId, messageId) {
    const response = await apiRetryMessage({
      path: { sessionId, messageId }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  }
};

// src/lib/api-client/git.ts
import {
  getGitStatus as apiGetGitStatus,
  getGitDiff as apiGetGitDiff,
  getGitBranch as apiGetGitBranch,
  stageFiles as apiStageFiles,
  unstageFiles as apiUnstageFiles,
  restoreFiles as apiRestoreFiles,
  deleteFiles as apiDeleteFiles,
  commitChanges as apiCommitChanges,
  generateCommitMessage as apiGenerateCommitMessage,
  pushCommits as apiPushCommits,
  pullChanges as apiPullChanges,
  performGitRebaseAction as apiPerformGitRebaseAction,
  initGitRepo as apiInitGitRepo,
  getGitRemotes as apiGetGitRemotes,
  addGitRemote as apiAddGitRemote,
  removeGitRemote as apiRemoveGitRemote,
  listGitBranches as apiListGitBranches,
  checkoutGitBranch as apiCheckoutGitBranch,
  createGitBranch as apiCreateGitBranch
} from "@ottocode/api";
var gitMixin = {
  async initGitRepo() {
    const response = await apiInitGitRepo({
      body: {}
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async getGitStatus() {
    const response = await apiGetGitStatus();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async getGitDiff(file, staged = false) {
    const response = await apiGetGitDiff({
      query: { file, staged: staged ? "true" : "false" }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async getGitDiffFullFile(file, staged = false) {
    const response = await apiGetGitDiff({
      query: {
        file,
        staged: staged ? "true" : "false",
        fullFile: "true"
      }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async generateCommitMessage(sessionId) {
    const response = await apiGenerateCommitMessage({
      body: sessionId ? { sessionId } : {}
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async stageFiles(files) {
    const response = await apiStageFiles({
      body: { files }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async unstageFiles(files) {
    const response = await apiUnstageFiles({
      body: { files }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async restoreFiles(files) {
    const response = await apiRestoreFiles({
      body: { files }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async deleteFiles(files) {
    const response = await apiDeleteFiles({
      body: { files }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async commitChanges(message) {
    const response = await apiCommitChanges({
      body: { message }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async getGitBranch() {
    const response = await apiGetGitBranch();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async pushCommits() {
    const response = await apiPushCommits({
      body: {}
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async pullChanges() {
    const response = await apiPullChanges({
      body: {}
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async performRebaseAction(action) {
    const response = await apiPerformGitRebaseAction({
      body: { action }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async getRemotes() {
    const response = await apiGetGitRemotes();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data?.remotes;
  },
  async addRemote(name, url) {
    const response = await apiAddGitRemote({
      body: { name, url }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async removeRemote(name) {
    const response = await apiRemoveGitRemote({
      body: { name }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async listGitBranches() {
    const response = await apiListGitBranches();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async checkoutBranch(branch) {
    const response = await apiCheckoutGitBranch({
      body: { branch }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  },
  async createGitBranch(name, options) {
    const response = await apiCreateGitBranch({
      body: {
        name,
        ...options?.startPoint ? { startPoint: options.startPoint } : {},
        ...options?.checkout !== undefined ? { checkout: options.checkout } : {}
      }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data?.data;
  }
};

// src/lib/api-client/config.ts
import {
  getConfig as apiGetConfig,
  getProviderModels as apiGetProviderModels,
  getAllModels as apiGetAllModels,
  discoverProviderModels as apiDiscoverProviderModels,
  updateDefaults as apiUpdateDefaults,
  updateProviderSettings as apiUpdateProviderSettings,
  deleteProviderSettings as apiDeleteProviderSettings
} from "@ottocode/api";
var configMixin = {
  async getConfig() {
    const response = await apiGetConfig();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getModels(providerId) {
    const response = await apiGetProviderModels({
      path: { provider: providerId }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getAllModels() {
    const response = await apiGetAllModels();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async discoverProviderModels(data) {
    const response = await apiDiscoverProviderModels({
      body: data
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async updateProviderSettings(provider, data) {
    const response = await apiUpdateProviderSettings({
      path: { provider },
      body: data
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async deleteProviderSettings(provider) {
    const response = await apiDeleteProviderSettings({
      path: { provider }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async updateDefaults(data) {
    const response = await apiUpdateDefaults({
      body: data
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  }
};

// src/lib/api-client/files.ts
import {
  listFiles as apiListFiles,
  searchFiles as apiSearchFiles,
  getFileTree as apiGetFileTree,
  readFile as apiReadFile,
  getSessionFiles as apiGetSessionFiles
} from "@ottocode/api";
var filesMixin = {
  async listFiles() {
    const response = await apiListFiles();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async searchFiles(query = "") {
    const response = await apiSearchFiles({ query: { q: query } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getFileTree(dirPath = ".") {
    const response = await apiGetFileTree({
      query: { path: dirPath }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async readFileContent(filePath) {
    const response = await apiReadFile({
      query: { path: filePath }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getSessionFiles(sessionId) {
    const response = await apiGetSessionFiles({ path: { sessionId } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  }
};

// src/lib/api-client/branches.ts
import {
  createBranch as apiCreateBranch,
  listBranches as apiListBranches,
  getParentSession as apiGetParentSession,
  getShareStatus as apiGetShareStatus,
  shareSession as apiShareSession,
  syncShare as apiSyncShare
} from "@ottocode/api";
var branchesMixin = {
  async createBranch(sessionId, data) {
    const response = await apiCreateBranch({
      path: { sessionId },
      body: data
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async listBranches(sessionId) {
    const response = await apiListBranches({ path: { sessionId } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getParentSession(sessionId) {
    const response = await apiGetParentSession({ path: { sessionId } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getShareStatus(sessionId) {
    const response = await apiGetShareStatus({ path: { sessionId } });
    if (response.error)
      return { shared: false };
    return response.data;
  },
  async shareSession(sessionId) {
    const response = await apiShareSession({ path: { sessionId } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async syncSession(sessionId) {
    const response = await apiSyncShare({ path: { sessionId } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  }
};

// src/lib/api-client/approval.ts
import {
  resolveApproval as apiResolveApproval,
  getPendingApprovals as apiGetPendingApprovals
} from "@ottocode/api";
var approvalMixin = {
  async approveToolCall(sessionId, callId, approved) {
    const response = await apiResolveApproval({
      path: { id: sessionId },
      body: { callId, approved, sessionId }
    });
    if (response.error)
      throw new Error("Failed to send tool approval");
    return response.data;
  },
  async getPendingApprovals(sessionId) {
    const response = await apiGetPendingApprovals({
      path: { id: sessionId }
    });
    if (response.error)
      return { ok: false, pending: [] };
    return response.data;
  }
};

// src/lib/api-client/ottorouter.ts
import {
  getOttoRouterBalance as apiGetOttoRouterBalance,
  getOttoRouterWallet as apiGetOttoRouterWallet,
  getOttoRouterUsdcBalance as apiGetOttoRouterUsdcBalance,
  createPolarCheckout as apiCreatePolarCheckout,
  getPolarTopupEstimate as apiGetPolarTopupEstimate,
  getPolarTopupStatus as apiGetPolarTopupStatus,
  getRazorpayTopupEstimate as apiGetRazorpayTopupEstimate,
  createRazorpayOrder as apiCreateRazorpayOrder,
  verifyRazorpayPayment as apiVerifyRazorpayPayment,
  selectTopupMethod as apiSelectTopupMethod,
  cancelTopup as apiCancelTopup,
  getPendingTopup as apiGetPendingTopup
} from "@ottocode/api";
var ottorouterMixin = {
  async getOttoRouterBalance() {
    try {
      const response = await apiGetOttoRouterBalance();
      if (response.error)
        return null;
      return response.data;
    } catch {
      return null;
    }
  },
  async getOttoRouterWallet() {
    try {
      const response = await apiGetOttoRouterWallet();
      if (response.error)
        return { configured: false };
      return response.data;
    } catch {
      return { configured: false };
    }
  },
  async getOttoRouterUsdcBalance(network = "mainnet") {
    try {
      const response = await apiGetOttoRouterUsdcBalance({
        query: { network }
      });
      if (response.error)
        return null;
      return response.data;
    } catch {
      return null;
    }
  },
  async getPolarTopupEstimate(amount) {
    try {
      const response = await apiGetPolarTopupEstimate({
        query: { amount }
      });
      if (response.error)
        return null;
      return response.data;
    } catch {
      return null;
    }
  },
  async createPolarCheckout(amount, successUrl) {
    const response = await apiCreatePolarCheckout({
      body: { amount, successUrl }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async selectTopupMethod(sessionId, method) {
    const response = await apiSelectTopupMethod({
      body: { sessionId, method }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async cancelTopup(sessionId, reason) {
    const response = await apiCancelTopup({
      body: { sessionId, reason }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getPendingTopup(sessionId) {
    try {
      const response = await apiGetPendingTopup({
        query: { sessionId }
      });
      if (response.error)
        return { hasPending: false };
      return response.data;
    } catch {
      return { hasPending: false };
    }
  },
  async getPolarTopupStatus(checkoutId) {
    try {
      const response = await apiGetPolarTopupStatus({
        query: { checkoutId }
      });
      if (response.error)
        return null;
      return response.data;
    } catch {
      return null;
    }
  },
  async getRazorpayTopupEstimate(amount) {
    try {
      const response = await apiGetRazorpayTopupEstimate({
        query: { amount }
      });
      if (response.error)
        return null;
      return response.data;
    } catch {
      return null;
    }
  },
  async createRazorpayOrder(amount) {
    const response = await apiCreateRazorpayOrder({
      body: { amount }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async verifyRazorpayPayment(params) {
    const response = await apiVerifyRazorpayPayment({
      body: params
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  }
};

// src/lib/api-client/auth.ts
import {
  getAuthStatus as apiGetAuthStatus,
  setupOttoRouterWallet as apiSetupOttoRouterWallet,
  importOttoRouterWallet as apiImportOttoRouterWallet,
  exportOttoRouterWallet as apiExportOttoRouterWallet,
  addProviderApiKey as apiAddProviderApiKey,
  removeProvider as apiRemoveProvider,
  completeOnboarding as apiCompleteOnboarding,
  getOAuthUrl as apiGetOAuthUrl,
  exchangeOAuthCode as apiExchangeOAuthCode,
  startOpenAiDeviceFlow as apiStartOpenAiDeviceFlow,
  pollOpenAiDeviceFlow as apiPollOpenAiDeviceFlow,
  startCopilotDeviceFlow as apiStartCopilotDeviceFlow,
  pollCopilotDeviceFlow as apiPollCopilotDeviceFlow,
  getCopilotAuthMethods as apiGetCopilotAuthMethods,
  saveCopilotToken as apiSaveCopilotToken,
  importCopilotTokenFromGh as apiImportCopilotTokenFromGh,
  getCopilotDiagnostics as apiGetCopilotDiagnostics,
  getProviderUsage as apiGetProviderUsage
} from "@ottocode/api";
var authMixin = {
  async getAuthStatus() {
    const response = await apiGetAuthStatus();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async setupOttoRouterWallet() {
    const response = await apiSetupOttoRouterWallet();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async importOttoRouterWallet(privateKey) {
    const response = await apiImportOttoRouterWallet({
      body: { privateKey }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async exportOttoRouterWallet() {
    const response = await apiExportOttoRouterWallet();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async addProvider(provider, apiKey) {
    const response = await apiAddProviderApiKey({
      path: { provider },
      body: { apiKey }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async removeProvider(provider) {
    const response = await apiRemoveProvider({ path: { provider } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async completeOnboarding() {
    const response = await apiCompleteOnboarding();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  getOAuthStartUrl(provider, mode) {
    const baseUrl = `${getBaseUrl()}/v1/auth/${provider}/oauth/start`;
    if (mode)
      return `${baseUrl}?mode=${mode}`;
    return baseUrl;
  },
  async getOAuthUrl(provider, mode) {
    const response = await apiGetOAuthUrl({
      path: { provider },
      body: { mode }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async exchangeOAuthCode(provider, code, sessionId) {
    const response = await apiExchangeOAuthCode({
      path: { provider },
      body: { code, sessionId }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async startOpenAIDeviceFlow() {
    const response = await apiStartOpenAiDeviceFlow();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async pollOpenAIDeviceFlow(sessionId) {
    const response = await apiPollOpenAiDeviceFlow({
      body: { sessionId }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async startCopilotDeviceFlow() {
    const response = await apiStartCopilotDeviceFlow();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async pollCopilotDeviceFlow(sessionId) {
    const response = await apiPollCopilotDeviceFlow({
      body: { sessionId }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getCopilotAuthMethods() {
    const response = await apiGetCopilotAuthMethods();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async saveCopilotToken(token) {
    const response = await apiSaveCopilotToken({ body: { token } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async importCopilotTokenFromGh() {
    const response = await apiImportCopilotTokenFromGh();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getCopilotDiagnostics() {
    const response = await apiGetCopilotDiagnostics();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getProviderUsage(provider) {
    const response = await apiGetProviderUsage({
      path: { provider }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  }
};

// src/lib/api-client/skills.ts
import {
  getSkillsConfig as apiGetSkillsConfig,
  updateSkillsConfig as apiUpdateSkillsConfig,
  listSkills as apiListSkills,
  getSkill as apiGetSkill,
  listSkillFiles as apiListSkillFiles,
  getSkillFile as apiGetSkillFile
} from "@ottocode/api";
var skillsMixin = {
  async listSkills() {
    const response = await apiListSkills();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getSkill(name) {
    const response = await apiGetSkill({ path: { name } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getSkillFiles(name) {
    const response = await apiListSkillFiles({ path: { name } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getSkillFileContent(name, filePath) {
    const response = await apiGetSkillFile({
      path: { name, filePath }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async getSkillsConfig() {
    const response = await apiGetSkillsConfig();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  async updateSkillsConfig(input) {
    const response = await apiUpdateSkillsConfig({ body: input });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  }
};

// src/lib/api-client/usage.ts
import {
  getUsageStats as apiGetUsageStats,
  getGlobalUsageStats as apiGetGlobalUsageStats
} from "@ottocode/api";
var usageMixin = {
  async getUsageStats() {
    const { data, error } = await apiGetUsageStats();
    if (error)
      throw new Error(extractErrorMessage(error));
    if (!data)
      throw new Error("Empty response from /v1/usage/stats");
    return data;
  },
  async getGlobalUsageStats() {
    const { data, error } = await apiGetGlobalUsageStats();
    if (error)
      throw new Error(extractErrorMessage(error));
    if (!data)
      throw new Error("Empty response from /v1/usage/stats/global");
    return data;
  }
};

// src/lib/api-client/dictation.ts
import {
  getDictationStatus as apiGetDictationStatus,
  installDictationModel as apiInstallDictationModel,
  listDictationModels as apiListDictationModels,
  removeDictationModel as apiRemoveDictationModel,
  createDictationSession as apiCreateDictationSession
} from "@ottocode/api";
function coerceModelState(value) {
  return value;
}
function coerceModels(value) {
  return Array.isArray(value) ? value.map(coerceModelState) : [];
}
function buildInstallEventsUrl(model) {
  const baseUrl = getBaseUrl().replace(/\/+$/, "");
  return `${baseUrl}/v1/dictation/models/${encodeURIComponent(model)}/install/events`;
}
var dictationMixin = {
  async getDictationStatus() {
    const response = await apiGetDictationStatus();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    const data = response.data;
    return {
      ...data,
      models: coerceModels(data.models)
    };
  },
  async listDictationModels() {
    const response = await apiListDictationModels();
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    const data = response.data;
    return { models: coerceModels(data.models) };
  },
  async installDictationModel({
    model,
    force
  }) {
    const response = await apiInstallDictationModel({
      path: { model },
      body: { force }
    });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    const data = response.data;
    return { model: coerceModelState(data.model) };
  },
  async removeDictationModel(model) {
    const response = await apiRemoveDictationModel({ path: { model } });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    const data = response.data;
    return {
      removed: data.removed,
      model: coerceModelState(data.model)
    };
  },
  async createDictationSession(input = {}) {
    const response = await apiCreateDictationSession({ body: input });
    if (response.error)
      throw new Error(extractErrorMessage(response.error));
    return response.data;
  },
  getDictationModelInstallEventsUrl: buildInstallEventsUrl
};

// src/lib/api-client/secure-input.ts
var secureInputMixin = {
  async submitSecureInput(sessionId, promptId, value) {
    const response = await fetch(`${getBaseUrl()}/v1/sessions/${encodeURIComponent(sessionId)}/secure-input`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ promptId, value })
    });
    if (!response.ok)
      throw new Error("Failed to submit secure input");
    return response.json();
  },
  async cancelSecureInput(sessionId, promptId) {
    const response = await fetch(`${getBaseUrl()}/v1/sessions/${encodeURIComponent(sessionId)}/secure-input`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ promptId, cancelled: true })
    });
    if (!response.ok)
      throw new Error("Failed to cancel secure input");
    return response.json();
  },
  async getPendingSecureInputs(sessionId) {
    const response = await fetch(`${getBaseUrl()}/v1/sessions/${encodeURIComponent(sessionId)}/secure-input/pending`);
    if (!response.ok)
      throw new Error("Failed to get pending secure inputs");
    return response.json();
  }
};

// src/lib/api-client/index.ts
class ApiClient {
  getSessions = sessionsMixin.getSessions;
  getSessionsPage = sessionsMixin.getSessionsPage;
  createSession = sessionsMixin.createSession;
  updateSession = sessionsMixin.updateSession;
  markSessionViewed = sessionsMixin.markSessionViewed;
  deleteSession = sessionsMixin.deleteSession;
  createHandoff = sessionsMixin.createHandoff;
  abortSession = sessionsMixin.abortSession;
  abortMessage = sessionsMixin.abortMessage;
  getQueueState = sessionsMixin.getQueueState;
  removeFromQueue = sessionsMixin.removeFromQueue;
  sendQueuedMessageNow = sessionsMixin.sendQueuedMessageNow;
  getMessages = sessionsMixin.getMessages;
  sendMessage = sessionsMixin.sendMessage;
  getStreamUrl = sessionsMixin.getStreamUrl;
  retryMessage = sessionsMixin.retryMessage;
  initGitRepo = gitMixin.initGitRepo;
  getGitStatus = gitMixin.getGitStatus;
  getGitDiff = gitMixin.getGitDiff;
  getGitDiffFullFile = gitMixin.getGitDiffFullFile;
  generateCommitMessage = gitMixin.generateCommitMessage;
  stageFiles = gitMixin.stageFiles;
  unstageFiles = gitMixin.unstageFiles;
  restoreFiles = gitMixin.restoreFiles;
  deleteFiles = gitMixin.deleteFiles;
  commitChanges = gitMixin.commitChanges;
  getGitBranch = gitMixin.getGitBranch;
  pushCommits = gitMixin.pushCommits;
  pullChanges = gitMixin.pullChanges;
  performRebaseAction = gitMixin.performRebaseAction;
  getRemotes = gitMixin.getRemotes;
  addRemote = gitMixin.addRemote;
  removeRemote = gitMixin.removeRemote;
  listGitBranches = gitMixin.listGitBranches;
  checkoutBranch = gitMixin.checkoutBranch;
  createGitBranch = gitMixin.createGitBranch;
  getConfig = configMixin.getConfig;
  getModels = configMixin.getModels;
  getAllModels = configMixin.getAllModels;
  discoverProviderModels = configMixin.discoverProviderModels;
  updateProviderSettings = configMixin.updateProviderSettings;
  deleteProviderSettings = configMixin.deleteProviderSettings;
  updateDefaults = configMixin.updateDefaults;
  listFiles = filesMixin.listFiles;
  searchFiles = filesMixin.searchFiles;
  getFileTree = filesMixin.getFileTree;
  readFileContent = filesMixin.readFileContent;
  getSessionFiles = filesMixin.getSessionFiles;
  createBranch = branchesMixin.createBranch;
  listBranches = branchesMixin.listBranches;
  getParentSession = branchesMixin.getParentSession;
  getShareStatus = branchesMixin.getShareStatus;
  shareSession = branchesMixin.shareSession;
  syncSession = branchesMixin.syncSession;
  approveToolCall = approvalMixin.approveToolCall;
  getPendingApprovals = approvalMixin.getPendingApprovals;
  submitSecureInput = secureInputMixin.submitSecureInput;
  cancelSecureInput = secureInputMixin.cancelSecureInput;
  getPendingSecureInputs = secureInputMixin.getPendingSecureInputs;
  getOttoRouterBalance = ottorouterMixin.getOttoRouterBalance;
  getOttoRouterWallet = ottorouterMixin.getOttoRouterWallet;
  getOttoRouterUsdcBalance = ottorouterMixin.getOttoRouterUsdcBalance;
  getPolarTopupEstimate = ottorouterMixin.getPolarTopupEstimate;
  createPolarCheckout = ottorouterMixin.createPolarCheckout;
  selectTopupMethod = ottorouterMixin.selectTopupMethod;
  cancelTopup = ottorouterMixin.cancelTopup;
  getPendingTopup = ottorouterMixin.getPendingTopup;
  getPolarTopupStatus = ottorouterMixin.getPolarTopupStatus;
  getRazorpayTopupEstimate = ottorouterMixin.getRazorpayTopupEstimate;
  createRazorpayOrder = ottorouterMixin.createRazorpayOrder;
  verifyRazorpayPayment = ottorouterMixin.verifyRazorpayPayment;
  getAuthStatus = authMixin.getAuthStatus;
  setupOttoRouterWallet = authMixin.setupOttoRouterWallet;
  importOttoRouterWallet = authMixin.importOttoRouterWallet;
  exportOttoRouterWallet = authMixin.exportOttoRouterWallet;
  addProvider = authMixin.addProvider;
  removeProvider = authMixin.removeProvider;
  completeOnboarding = authMixin.completeOnboarding;
  getOAuthStartUrl = authMixin.getOAuthStartUrl;
  getOAuthUrl = authMixin.getOAuthUrl;
  exchangeOAuthCode = authMixin.exchangeOAuthCode;
  startOpenAIDeviceFlow = authMixin.startOpenAIDeviceFlow;
  pollOpenAIDeviceFlow = authMixin.pollOpenAIDeviceFlow;
  startCopilotDeviceFlow = authMixin.startCopilotDeviceFlow;
  pollCopilotDeviceFlow = authMixin.pollCopilotDeviceFlow;
  getCopilotAuthMethods = authMixin.getCopilotAuthMethods;
  saveCopilotToken = authMixin.saveCopilotToken;
  importCopilotTokenFromGh = authMixin.importCopilotTokenFromGh;
  getCopilotDiagnostics = authMixin.getCopilotDiagnostics;
  getProviderUsage = authMixin.getProviderUsage;
  listSkills = skillsMixin.listSkills;
  getSkill = skillsMixin.getSkill;
  getSkillFiles = skillsMixin.getSkillFiles;
  getSkillFileContent = skillsMixin.getSkillFileContent;
  getSkillsConfig = skillsMixin.getSkillsConfig;
  updateSkillsConfig = skillsMixin.updateSkillsConfig;
  getUsageStats = usageMixin.getUsageStats;
  getGlobalUsageStats = usageMixin.getGlobalUsageStats;
  getDictationStatus = dictationMixin.getDictationStatus;
  listDictationModels = dictationMixin.listDictationModels;
  installDictationModel = dictationMixin.installDictationModel;
  removeDictationModel = dictationMixin.removeDictationModel;
  createDictationSession = dictationMixin.createDictationSession;
  getDictationModelInstallEventsUrl = dictationMixin.getDictationModelInstallEventsUrl;
}
var apiClient = new ApiClient;
// src/lib/sse-client.ts
class SSEClient {
  abortController = null;
  handlers = new Map;
  running = false;
  async connect(url) {
    if (this.abortController) {
      this.abortController.abort();
    }
    this.abortController = new AbortController;
    this.running = true;
    const isTunnel = !url.includes("localhost") && !url.includes("127.0.0.1");
    try {
      const response = await fetch(url, {
        method: isTunnel ? "POST" : "GET",
        headers: { Accept: "text/event-stream" },
        signal: this.abortController.signal
      });
      if (!response.ok) {
        console.error("[SSE] Connection failed:", response.status);
        return;
      }
      const reader = response.body?.getReader();
      if (!reader) {
        console.error("[SSE] No response body");
        return;
      }
      const decoder = new TextDecoder;
      let buffer = "";
      while (this.running) {
        const { done, value } = await reader.read();
        if (done)
          break;
        buffer += decoder.decode(value, { stream: true });
        let idx = buffer.indexOf(`

`);
        while (idx !== -1) {
          const raw = buffer.slice(0, idx);
          buffer = buffer.slice(idx + 2);
          const lines = raw.split(`
`);
          let eventType = "message";
          let data = "";
          for (const line of lines) {
            if (line.startsWith("event: ")) {
              eventType = line.slice(7).trim();
            } else if (line.startsWith("data: ")) {
              data += (data ? `
` : "") + line.slice(6);
            } else if (line.startsWith(":")) {}
          }
          if (data) {
            try {
              const payload = JSON.parse(data);
              this.emit({ type: eventType, payload });
            } catch (error) {
              console.error(`[SSE] Failed to parse ${eventType}:`, error);
            }
          }
          idx = buffer.indexOf(`

`);
        }
      }
    } catch (error) {
      if (error instanceof Error && error.name === "AbortError") {} else if (error instanceof TypeError && error.message === "Load failed") {} else {
        console.error("[SSE] Connection error:", error);
      }
    }
  }
  disconnect() {
    this.running = false;
    if (this.abortController) {
      this.abortController.abort();
      this.abortController = null;
    }
  }
  on(eventType, handler) {
    if (!this.handlers.has(eventType)) {
      this.handlers.set(eventType, new Set);
    }
    this.handlers.get(eventType)?.add(handler);
    return () => {
      this.off(eventType, handler);
    };
  }
  off(eventType, handler) {
    const handlers = this.handlers.get(eventType);
    if (handlers) {
      handlers.delete(handler);
      if (handlers.size === 0) {
        this.handlers.delete(eventType);
      }
    }
  }
  emit(event) {
    const handlers = this.handlers.get(event.type);
    if (handlers) {
      for (const handler of handlers) {
        handler(event);
      }
    }
    const allHandlers = this.handlers.get("*");
    if (allHandlers) {
      for (const handler of allHandlers) {
        handler(event);
      }
    }
  }
}
export {
  showPlatformNotification,
  setRuntimeApiBaseUrl,
  openPlatformUrl,
  openPlatformSession,
  notifyPlatformFontFamilyChanged,
  normalizeApiBaseUrl,
  listPlatformSystemFonts,
  isPlatformDesktop,
  hasPlatformSystemFonts,
  hasPlatformOpenUrl,
  hasConfiguredRuntimeApiBaseUrl,
  getRuntimeApiBaseUrl,
  getPlatformWindowFocused,
  getConfiguredRuntimeApiBaseUrl,
  configureApiClient,
  config,
  clearRuntimeApiBaseUrl,
  apiClient,
  SSEClient,
  RUNTIME_API_BASE_URL_STORAGE_KEY,
  API_BASE_URL
};

//# debugId=275BCE73BE2B1B8A64756E2164756E21
