import { createRequire } from "node:module";
var __require = /* @__PURE__ */ createRequire(import.meta.url);

// src/hooks.ts
var hooks = null;
function configure(next) {
  hooks = next;
}
function requireCodeWorkDir() {
  if (!hooks?.getCodeWorkDir) {
    throw new Error("CodeTool: code work directory not configured");
  }
  const dir = hooks.getCodeWorkDir();
  if (!dir || !dir.trim()) {
    throw new Error("CodeTool: code work directory not configured");
  }
  return dir;
}
function getCodeMdExcludes() {
  return hooks?.getCodeMdExcludes?.() ?? [];
}

// src/memory/loadCodeMd.ts
import { readFile, readdir, stat } from "node:fs/promises";
import { dirname, join, parse } from "node:path";

// src/memory/constants.ts
var CODE_MD = "code.md";
var CODE_LOCAL_MD = "code.local.md";
var RULES_DIR = ".claude/rules";
var MEMORY_INSTRUCTION_PROMPT = "Codebase and user instructions are shown below. Be sure to adhere to these instructions. IMPORTANT: These instructions OVERRIDE any default behavior and you MUST follow them exactly as written.";
var MAX_MEMORY_CHARACTER_COUNT = 40000;

// src/memory/loadCodeMd.ts
function stripFrontmatter(raw) {
  if (!raw.startsWith("---")) {
    return { content: raw };
  }
  const end = raw.indexOf("---", 3);
  if (end === -1) {
    return { content: raw };
  }
  const body = raw.slice(end + 3).replace(/^\n/, "");
  const fm = raw.slice(3, end);
  const pathsMatch = fm.match(/^paths:\s*(.+)$/m);
  if (!pathsMatch) {
    return { content: body };
  }
  const paths = pathsMatch[1].split(",").map((p) => p.trim()).filter((p) => p.length > 0 && p !== "**");
  return { content: body, globs: paths.length > 0 ? paths : undefined };
}
function normalizePath(p) {
  return p.replaceAll("\\", "/");
}
function isExcluded(filePath, excludes) {
  if (excludes.length === 0)
    return false;
  const norm = normalizePath(filePath);
  for (const pat of excludes) {
    const p = normalizePath(pat.trim());
    if (!p)
      continue;
    if (p.includes("*")) {
      if (norm.includes(p.replace(/\*\*/g, "").replace(/\*/g, "")))
        return true;
    } else if (norm === p || norm.endsWith(p)) {
      return true;
    }
  }
  return false;
}
async function fileExists(path) {
  try {
    await stat(path);
    return true;
  } catch {
    return false;
  }
}
async function readMemoryFile(filePath, type) {
  try {
    const raw = await readFile(filePath, "utf8");
    const trimmed = raw.trim();
    if (!trimmed)
      return null;
    const { content, globs } = stripFrontmatter(raw);
    if (!content.trim())
      return null;
    return { path: filePath, type, content, globs };
  } catch {
    return null;
  }
}
async function loadRulesDir(rulesDir, type, processed) {
  const out = [];
  let entries;
  try {
    entries = await readdir(rulesDir, { withFileTypes: true });
  } catch {
    return out;
  }
  for (const e of entries) {
    const p = join(rulesDir, e.name);
    if (e.isDirectory()) {
      out.push(...await loadRulesDir(p, type, processed));
    } else if (e.isFile() && e.name.endsWith(".md")) {
      const key = normalizePath(p);
      if (processed.has(key))
        continue;
      processed.add(key);
      const info = await readMemoryFile(p, type);
      if (info && !info.globs)
        out.push(info);
    }
  }
  return out;
}
async function collectMemoryFiles(projectRoot, excludes = []) {
  const result = [];
  const processed = new Set;
  const dirs = [];
  let cur = projectRoot;
  const root = parse(cur).root;
  while (cur !== root) {
    dirs.push(cur);
    cur = dirname(cur);
  }
  dirs.reverse();
  for (const dir of dirs) {
    const candidates = [
      { path: join(dir, CODE_MD), type: "Project" },
      { path: join(dir, ".claude", "code.md"), type: "Project" },
      { path: join(dir, CODE_LOCAL_MD), type: "Local" }
    ];
    for (const { path, type } of candidates) {
      if (isExcluded(path, excludes))
        continue;
      const key = normalizePath(path);
      if (processed.has(key))
        continue;
      if (!await fileExists(path))
        continue;
      processed.add(key);
      const info = await readMemoryFile(path, type);
      if (info)
        result.push(info);
    }
    const rulesPath = join(dir, RULES_DIR);
    result.push(...await loadRulesDir(rulesPath, "Project", processed));
  }
  return result;
}
function formatCodeMd(memoryFiles) {
  const parts = [];
  for (const file of memoryFiles) {
    const content = file.content.trim();
    if (!content)
      continue;
    const desc = file.type === "Project" ? " (project instructions, checked into the codebase)" : " (user's private project instructions, not checked in)";
    parts.push(`Contents of ${file.path}${desc}:

${content}`);
  }
  if (parts.length === 0)
    return "";
  return `${MEMORY_INSTRUCTION_PROMPT}

${parts.join(`

`)}`;
}
async function loadCodeMd(options) {
  const files = await collectMemoryFiles(options.projectRoot, options.excludes ?? []);
  let text = formatCodeMd(files);
  const max = options.maxChars ?? MAX_MEMORY_CHARACTER_COUNT;
  if (text.length > max) {
    text = `${text.slice(0, max)}

[truncated: code memory exceeded ${max} characters]`;
  }
  return text;
}

// src/projectScan.ts
import { readFile as readFile2, readdir as readdir2, stat as stat2 } from "node:fs/promises";
import { join as join2 } from "node:path";
var MANIFEST_NAMES = [
  "package.json",
  "go.mod",
  "Cargo.toml",
  "pyproject.toml",
  "pom.xml",
  "Makefile"
];
async function scanProjectBrief(codeWorkDir, maxDepth = 2) {
  const manifests = {};
  for (const name of MANIFEST_NAMES) {
    const p = join2(codeWorkDir, name);
    try {
      const st = await stat2(p);
      if (st.isFile()) {
        const raw = await readFile2(p, "utf8");
        manifests[name] = raw.length > 8000 ? `${raw.slice(0, 8000)}…` : raw;
      }
    } catch {}
  }
  const tree = [];
  await walkDir(codeWorkDir, "", 0, maxDepth, tree);
  return { manifests, tree };
}
async function walkDir(root, rel, depth, maxDepth, out) {
  if (depth > maxDepth)
    return;
  const full = rel ? join2(root, rel) : root;
  let entries;
  try {
    entries = await readdir2(full, { withFileTypes: true });
  } catch {
    return;
  }
  const sorted = entries.filter((e) => !e.name.startsWith(".") && e.name !== "node_modules").sort((a, b) => a.name.localeCompare(b.name));
  for (const e of sorted.slice(0, 40)) {
    const childRel = rel ? `${rel}/${e.name}` : e.name;
    out.push(`${"  ".repeat(depth)}${e.name}${e.isDirectory() ? "/" : ""}`);
    if (e.isDirectory() && depth < maxDepth) {
      await walkDir(root, childRel, depth + 1, maxDepth, out);
    }
  }
}

// src/actions/inspect.ts
async function runInspect(brief) {
  const codeWorkDir = requireCodeWorkDir();
  const memory = await loadCodeMd({
    projectRoot: codeWorkDir,
    excludes: getCodeMdExcludes(),
    maxChars: brief ? 12000 : undefined
  });
  const { manifests, tree } = await scanProjectBrief(codeWorkDir);
  let readme = "";
  try {
    const { readFile: readFile3 } = await import("node:fs/promises");
    const { join: join3 } = await import("node:path");
    readme = await readFile3(join3(codeWorkDir, "README.md"), "utf8");
    if (readme.length > 6000)
      readme = `${readme.slice(0, 6000)}…`;
  } catch {
    readme = "";
  }
  return {
    codeWorkDir,
    codeMemory: memory,
    hasCodeMemory: memory.length > 0,
    readme: brief && readme.length > 2000 ? `${readme.slice(0, 2000)}…` : readme,
    manifests: brief ? Object.keys(manifests) : manifests,
    tree: brief ? tree.slice(0, 40) : tree
  };
}

// src/cli.ts
async function main() {
  const args = process.argv.slice(2);
  const workDirIdx = args.indexOf("--work-dir");
  let workDir = process.env.CODE_WORK_DIR?.trim() ?? "";
  if (workDirIdx >= 0 && args[workDirIdx + 1]) {
    workDir = args[workDirIdx + 1];
    args.splice(workDirIdx, 2);
  }
  if (!workDir) {
    console.error("[code-tool-cli] CODE_WORK_DIR 或 --work-dir 必填");
    process.exit(1);
  }
  configure({ getCodeWorkDir: () => workDir });
  const cmd = args[0];
  if (cmd === "inspect" && args.includes("--brief")) {
    const data = await runInspect(true);
    const mem = String(data.codeMemory ?? "");
    if (mem) {
      process.stdout.write(mem);
    } else {
      process.stdout.write(`（尚无 code.md；开发任务开始后请 CodeTool.record 首建并写入 overview/commands）
`);
    }
    return;
  }
  console.error("[code-tool-cli] 仅支持: inspect --brief [--work-dir PATH]");
  process.exit(1);
}
main().catch((e) => {
  console.error(`[code-tool-cli] ${e instanceof Error ? e.message : String(e)}`);
  process.exit(1);
});
