// Force strict mode and setup for ESM
"use strict";
import {
  require_undici
} from "./chunk-M2U5NM24.js";
import {
  writeStderrLine
} from "./chunk-Y6Z2O3WR.js";
import {
  createDebugLogger
} from "./chunk-UX4SGCGN.js";
import {
  init_esbuild_shims
} from "./chunk-A4BMJM77.js";
import {
  __name,
  __toESM
} from "./chunk-J2S4EL5Y.js";

// packages/cli/src/services/setup-github.ts
init_esbuild_shims();
var import_undici2 = __toESM(require_undici(), 1);
import { promises as fsp } from "node:fs";
import * as path from "node:path";

// packages/cli/src/utils/gitUtils.ts
init_esbuild_shims();
var import_undici = __toESM(require_undici(), 1);
import * as childProcess from "node:child_process";
var debugLogger = createDebugLogger("GIT");
async function runGit(args, opts = {}) {
  return await new Promise((resolve2, reject) => {
    childProcess.execFile(
      "git",
      args,
      {
        encoding: "utf-8",
        ...opts.cwd ? { cwd: opts.cwd } : {}
      },
      (err, stdout) => {
        if (err) {
          reject(err);
          return;
        }
        resolve2(String(stdout ?? "").trim());
      }
    );
  });
}
__name(runGit, "runGit");
var isGitHubRepositoryAsync = /* @__PURE__ */ __name(async (opts = {}) => {
  try {
    const remotes = await runGit(["remote", "-v"], opts);
    return remotes.split("\n").some((line) => {
      const remoteUrl = line.trim().split(/\s+/)[1];
      return remoteUrl ? isGitHubRemoteUrl(remoteUrl) : false;
    });
  } catch (_error) {
    debugLogger.debug(`Failed to get git remote:`, _error);
    return false;
  }
}, "isGitHubRepositoryAsync");
function isGitHubRemoteUrl(remoteUrl) {
  if (remoteUrl.startsWith("git@github.com:")) {
    return true;
  }
  if (remoteUrl.startsWith("git@")) {
    return false;
  }
  try {
    return new URL(remoteUrl).hostname === "github.com";
  } catch {
    return false;
  }
}
__name(isGitHubRemoteUrl, "isGitHubRemoteUrl");
var getGitRepoRootAsync = /* @__PURE__ */ __name(async (opts = {}) => {
  const gitRepoRoot = await runGit(["rev-parse", "--show-toplevel"], opts);
  if (!gitRepoRoot) {
    throw new Error(`Git repo returned empty value`);
  }
  return gitRepoRoot;
}, "getGitRepoRootAsync");
var getLatestGitHubRelease = /* @__PURE__ */ __name(async (proxy) => {
  try {
    const controller = new AbortController();
    const endpoint = `https://api.github.com/repos/QwenLM/qwen-code-action/releases/latest`;
    const response = await fetch(endpoint, {
      method: "GET",
      headers: {
        Accept: "application/vnd.github+json",
        "Content-Type": "application/json",
        "X-GitHub-Api-Version": "2022-11-28"
      },
      dispatcher: proxy ? new import_undici.ProxyAgent(proxy) : void 0,
      signal: AbortSignal.any([AbortSignal.timeout(3e4), controller.signal])
    });
    if (!response.ok) {
      throw new Error(
        `Invalid response code: ${response.status} - ${response.statusText}`
      );
    }
    const releaseTag = (await response.json()).tag_name;
    if (!releaseTag) {
      throw new Error(`Response did not include tag_name field`);
    }
    return releaseTag;
  } catch (_error) {
    debugLogger.debug(
      `Failed to determine latest qwen-code-action release:`,
      _error
    );
    throw new Error(
      `Unable to determine the latest qwen-code-action release on GitHub.`
    );
  }
}, "getLatestGitHubRelease");
async function getGitHubRepoInfoAsync(opts = {}) {
  return parseGitHubRepoInfo(
    await runGit(["remote", "get-url", "origin"], opts)
  );
}
__name(getGitHubRepoInfoAsync, "getGitHubRepoInfoAsync");
function parseGitHubRepoInfo(remoteUrl) {
  let urlToParse = remoteUrl;
  if (remoteUrl.startsWith("git@github.com:")) {
    urlToParse = remoteUrl.replace("git@github.com:", "");
  } else if (remoteUrl.startsWith("git@")) {
    throw new Error(
      `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
    );
  }
  let parsedUrl;
  try {
    parsedUrl = new URL(urlToParse, "https://github.com");
  } catch {
    throw new Error(
      `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
    );
  }
  if (parsedUrl.hostname !== "github.com") {
    throw new Error(
      `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
    );
  }
  const parts = parsedUrl.pathname.split("/").filter((part) => part !== "");
  if (parts.length !== 2 || !parts[0] || !parts[1]) {
    throw new Error(
      `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
    );
  }
  return { owner: parts[0], repo: parts[1].replace(/\.git$/, "") };
}
__name(parseGitHubRepoInfo, "parseGitHubRepoInfo");

// packages/cli/src/services/setup-github.ts
var debugLogger2 = createDebugLogger("SETUP_GITHUB");
var GITHUB_WORKFLOW_PATHS = [
  "qwen-dispatch/qwen-dispatch.yml",
  "qwen-assistant/qwen-invoke.yml",
  "issue-triage/qwen-triage.yml",
  "issue-triage/qwen-scheduled-triage.yml",
  "pr-review/qwen-review.yml"
];
var GITIGNORE_ENTRIES = [".qwen/", "gha-creds-*.json"];
var MAX_WORKFLOW_DOWNLOAD_BYTES = 5 * 1024 * 1024;
var SetupGithubError = class extends Error {
  static {
    __name(this, "SetupGithubError");
  }
  code;
  status;
  partial;
  partialResult;
  constructor(code, message, status, partialResult) {
    super(message);
    this.name = "SetupGithubError";
    this.code = code;
    this.status = status;
    this.partial = partialResult !== void 0;
    this.partialResult = partialResult;
  }
};
var nodeFileOps = {
  assertCanWrite() {
  },
  async ensureWorkflowDirectory(gitRepoRoot) {
    await fsp.mkdir(path.join(gitRepoRoot, ".github", "workflows"), {
      recursive: true
    });
  },
  async writeTextFile(gitRepoRoot, relativePath, content) {
    const target = path.join(gitRepoRoot, relativePath);
    await fsp.writeFile(target, content, { mode: 420 });
    return { sizeBytes: Buffer.byteLength(content, "utf8") };
  },
  async readTextFile(gitRepoRoot, relativePath) {
    try {
      return await fsp.readFile(path.join(gitRepoRoot, relativePath), "utf8");
    } catch (error) {
      if (error.code === "ENOENT") {
        return void 0;
      }
      throw error;
    }
  }
};
async function setupGithub(options = {}) {
  const cwd = options.cwd ?? process.cwd();
  const fileOps = options.fileOps ?? nodeFileOps;
  if (!await isGitHubRepositoryAsync({ cwd })) {
    throw new SetupGithubError(
      "github_repository_not_found",
      "Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
      400
    );
  }
  let gitRepoRoot;
  try {
    gitRepoRoot = await getGitRepoRootAsync({ cwd });
  } catch (error) {
    debugLogger2.debug("Failed to get git repo root:", error);
    throw new SetupGithubError(
      "github_repository_not_found",
      "Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
      400
    );
  }
  if (options.workspaceRoot) {
    const [gitRootReal, workspaceReal] = await Promise.all([
      realpathOrResolve(gitRepoRoot),
      realpathOrResolve(options.workspaceRoot)
    ]);
    if (gitRootReal !== workspaceReal) {
      throw new SetupGithubError(
        "github_git_root_mismatch",
        "The Git repository root must match the daemon workspace root.",
        400
      );
    }
  }
  fileOps.assertCanWrite?.();
  let releaseTag;
  try {
    releaseTag = await getLatestGitHubRelease(options.proxy);
  } catch (error) {
    writeStderrLine(
      `qwen setup-github: failed to determine latest qwen-code-action release: ${error instanceof Error ? error.message : String(error)}`
    );
    debugLogger2.debug(
      "Failed to determine latest qwen-code-action release:",
      error
    );
    throw new SetupGithubError(
      "github_release_lookup_failed",
      "Unable to determine the latest qwen-code-action release on GitHub.",
      502
    );
  }
  const readmeUrl = `https://github.com/QwenLM/qwen-code-action/blob/${releaseTag}/README.md#quick-start`;
  const secretsUrl = await resolveSecretsUrl(cwd);
  const downloads = await downloadWorkflows({
    releaseTag,
    proxy: options.proxy,
    abortSignal: options.abortSignal,
    fetchImpl: options.fetchImpl ?? fetch
  });
  const result = {
    kind: "github_setup",
    workspaceCwd: options.workspaceRoot ?? gitRepoRoot,
    gitRepoRoot,
    releaseTag,
    readmeUrl,
    ...secretsUrl ? { secretsUrl } : {},
    workflows: [],
    gitignore: { path: ".gitignore", status: "skipped" },
    warnings: []
  };
  result.gitignore = await updateGitignore(gitRepoRoot, fileOps);
  if (result.gitignore.status === "failed") {
    result.warnings.push("Failed to update .gitignore.");
  }
  try {
    await fileOps.ensureWorkflowDirectory(gitRepoRoot);
    for (const workflow of downloads) {
      const relativePath = path.posix.join(
        ".github",
        "workflows",
        path.posix.basename(workflow.sourcePath)
      );
      try {
        const write = await fileOps.writeTextFile(
          gitRepoRoot,
          relativePath,
          workflow.content
        );
        result.workflows.push({
          sourcePath: workflow.sourcePath,
          path: relativePath,
          status: "written",
          sizeBytes: write.sizeBytes
        });
      } catch (error) {
        result.partial = true;
        result.workflows.push({
          sourcePath: workflow.sourcePath,
          path: relativePath,
          status: "failed",
          error: error instanceof Error ? error.message : String(error)
        });
        throw new SetupGithubError(
          "github_workflow_write_failed",
          `Unable to write ${relativePath}.`,
          500,
          result
        );
      }
    }
  } catch (error) {
    if (error instanceof SetupGithubError) throw error;
    throw new SetupGithubError(
      "github_workflow_write_failed",
      "Unable to create .github/workflows.",
      500,
      result
    );
  }
  return result;
}
__name(setupGithub, "setupGithub");
async function updateGitignore(gitRepoRoot, fileOps = nodeFileOps) {
  try {
    const existingContent = await fileOps.readTextFile(
      gitRepoRoot,
      ".gitignore"
    );
    if (existingContent === void 0) {
      const content = GITIGNORE_ENTRIES.join("\n") + "\n";
      await fileOps.writeTextFile(gitRepoRoot, ".gitignore", content);
      return {
        path: ".gitignore",
        status: "created",
        added: [...GITIGNORE_ENTRIES]
      };
    }
    const missingEntries = GITIGNORE_ENTRIES.filter(
      (entry) => !existingContent.split(/\r?\n/).some((line) => line.split("#")[0].trim() === entry)
    );
    if (missingEntries.length === 0) {
      return { path: ".gitignore", status: "unchanged" };
    }
    const nextContent = existingContent + "\n" + missingEntries.join("\n") + "\n";
    await fileOps.writeTextFile(gitRepoRoot, ".gitignore", nextContent);
    return {
      path: ".gitignore",
      status: "updated",
      added: missingEntries
    };
  } catch (error) {
    debugLogger2.debug("Failed to update .gitignore:", error);
    return {
      path: ".gitignore",
      status: "failed",
      error: error instanceof Error ? error.message : String(error)
    };
  }
}
__name(updateGitignore, "updateGitignore");
async function downloadWorkflows(options) {
  const internalAbort = new AbortController();
  try {
    const dispatcher = options.proxy ? new import_undici2.ProxyAgent(options.proxy) : void 0;
    return await Promise.all(
      GITHUB_WORKFLOW_PATHS.map(async (workflow) => {
        const endpoint = `https://raw.githubusercontent.com/QwenLM/qwen-code-action/refs/tags/${options.releaseTag}/examples/workflows/${workflow}`;
        const response = await options.fetchImpl(endpoint, {
          method: "GET",
          dispatcher,
          signal: AbortSignal.any([
            AbortSignal.timeout(3e4),
            internalAbort.signal,
            ...options.abortSignal ? [options.abortSignal] : []
          ])
        });
        if (!response.ok) {
          throw new Error(
            `Invalid response code downloading ${endpoint}: ${response.status} - ${response.statusText}`
          );
        }
        return {
          sourcePath: workflow,
          content: await readResponseTextWithLimit(response, workflow)
        };
      })
    );
  } catch (error) {
    internalAbort.abort();
    const message = error instanceof Error ? error.message : String(error);
    debugLogger2.debug("Failed to download qwen-code-action workflows:", error);
    throw new SetupGithubError(
      "github_workflow_download_failed",
      `Unable to download qwen-code-action workflows from GitHub. ${message}`,
      502
    );
  }
}
__name(downloadWorkflows, "downloadWorkflows");
async function readResponseTextWithLimit(response, sourcePath) {
  const contentLength = response.headers.get("content-length");
  if (contentLength !== null) {
    const parsedLength = Number(contentLength);
    if (Number.isFinite(parsedLength) && parsedLength > MAX_WORKFLOW_DOWNLOAD_BYTES) {
      throw new Error(
        `${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
      );
    }
  }
  if (!response.body) return "";
  const reader = response.body.getReader();
  const chunks = [];
  let totalBytes = 0;
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      if (!value) continue;
      totalBytes += value.byteLength;
      if (totalBytes > MAX_WORKFLOW_DOWNLOAD_BYTES) {
        await reader.cancel().catch(() => {
        });
        throw new Error(
          `${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
        );
      }
      chunks.push(value);
    }
  } finally {
    reader.releaseLock();
  }
  const body = new Uint8Array(totalBytes);
  let offset = 0;
  for (const chunk of chunks) {
    body.set(chunk, offset);
    offset += chunk.byteLength;
  }
  return new TextDecoder().decode(body);
}
__name(readResponseTextWithLimit, "readResponseTextWithLimit");
async function resolveSecretsUrl(cwd) {
  try {
    const repoInfo = await getGitHubRepoInfoAsync({ cwd });
    return `https://github.com/${repoInfo.owner}/${repoInfo.repo}/settings/secrets/actions`;
  } catch {
    return void 0;
  }
}
__name(resolveSecretsUrl, "resolveSecretsUrl");
async function realpathOrResolve(input) {
  try {
    return await fsp.realpath(input);
  } catch {
    return path.resolve(input);
  }
}
__name(realpathOrResolve, "realpathOrResolve");

export {
  GITHUB_WORKFLOW_PATHS,
  SetupGithubError,
  setupGithub
};
/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2025 Qwen Team
 * SPDX-License-Identifier: Apache-2.0
 */
