'use strict';

require('fs');
var path3 = require('path');
require('child_process');
require('util');
require('url');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var path3__default = /*#__PURE__*/_interopDefault(path3);

// src/features/token-optimizer/infrastructure/config.ts
var DEFAULT_TOKEN_OPTIMIZER_STATE = {
  enabled: false
};
var tokenOptimizerRuntimeState = globalThis.__JU_HONG_E_TOKEN_OPTIMIZER_STATE__ ?? (globalThis.__JU_HONG_E_TOKEN_OPTIMIZER_STATE__ = {
  ...DEFAULT_TOKEN_OPTIMIZER_STATE
});
function isTokenOptimizerEnabled(paths) {
  return tokenOptimizerRuntimeState.enabled;
}
function safeExcerpt(content, limit = 3e3) {
  if (!content) {
    return "";
  }
  if (content.length <= limit) {
    return content;
  }
  return `${content.slice(0, limit)}
... (truncated ${content.length - limit} chars)`;
}

// src/platform/token-optimizer/strip-ansi.ts
var ANSI_REGEX = new RegExp(
  String.raw`\u001B\[[0-9;]*[a-zA-Z]|\u001B\].*?(?:\u0007|\u001B\\)`,
  "g"
);
var stripAnsi = (text) => {
  return text.replace(ANSI_REGEX, "");
};

// src/platform/token-optimizer/token-counter.ts
var countTokens = (text) => {
  if (!text) {
    return 0;
  }
  return text.split(/\s+/).filter(Boolean).length;
};

// src/platform/token-optimizer/truncate.ts
var truncateText = (text, maxLength) => {
  const charCount = [...text].length;
  if (charCount <= maxLength) {
    return text;
  }
  if (maxLength < 3) {
    return "...";
  }
  return [...text].slice(0, maxLength - 3).join("") + "...";
};
var truncateLines = (text, options) => {
  const { maxCharsPerLine, headLines, tailLines, maxLines } = options;
  let lines = text.split("\n");
  if (headLines !== void 0 && tailLines !== void 0 && lines.length > headLines + tailLines) {
    const head = lines.slice(0, headLines);
    const tail = lines.slice(-tailLines);
    const omittedCount = lines.length - headLines - tailLines;
    lines = [...head, `... (${omittedCount}\uC904 \uC0DD\uB7B5)`, ...tail];
  } else if (headLines !== void 0 && lines.length > headLines) {
    const omittedCount = lines.length - headLines;
    lines = [...lines.slice(0, headLines), `... (${omittedCount}\uC904 \uC0DD\uB7B5)`];
  } else if (tailLines !== void 0 && lines.length > tailLines) {
    const omittedCount = lines.length - tailLines;
    lines = [`... (${omittedCount}\uC904 \uC0DD\uB7B5)`, ...lines.slice(-tailLines)];
  }
  if (maxCharsPerLine !== void 0) {
    lines = lines.map((line) => truncateText(line, maxCharsPerLine));
  }
  if (maxLines !== void 0 && lines.length > maxLines) {
    if (maxLines <= 0) {
      return "";
    }
    const preservedLineCount = Math.max(maxLines - 1, 0);
    const omittedCount = lines.length - preservedLineCount;
    lines = preservedLineCount === 0 ? [`... (${omittedCount}\uC904 \uC0DD\uB7B5)`] : [...lines.slice(0, preservedLineCount), `... (${omittedCount}\uC904 \uC0DD\uB7B5)`];
  }
  return lines.join("\n");
};

// src/platform/token-optimizer/line-filter.ts
function matchesLine(pattern, line) {
  const safePattern = pattern.global || pattern.sticky ? new RegExp(pattern.source, pattern.flags) : pattern;
  safePattern.lastIndex = 0;
  return safePattern.test(line);
}
var filterLines = (text, options) => {
  const { keepPatterns, stripPatterns, stripEmptyLines } = options;
  let lines = text.split("\n");
  if (keepPatterns && keepPatterns.length > 0) {
    lines = lines.filter((line) => keepPatterns.some((pattern) => matchesLine(pattern, line)));
  }
  if (stripPatterns && stripPatterns.length > 0) {
    lines = lines.filter((line) => !stripPatterns.some((pattern) => matchesLine(pattern, line)));
  }
  if (stripEmptyLines) {
    lines = lines.filter((line) => line.trim().length > 0);
  }
  return lines.join("\n");
};

// src/platform/token-optimizer/deduplication.ts
var NORMALIZATION_RULES = [
  // ISO 타임스탬프 (2026-04-09T10:00:01.123 또는 2026-04-09 10:00:01)
  [/\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}[.\d]*/g, "<TIMESTAMP>"],
  // 대괄호 타임스탬프 ([10:00:01], [2026-04-09 10:00:01])
  [/\[\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}[.\d]*\]/g, "[<TIMESTAMP>]"],
  // UUID
  [/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, "<UUID>"],
  // IP 주소
  [/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/g, "<IP>"],
  // 16진수 해시 (7자 이상)
  [/\b[0-9a-f]{7,}\b/gi, "<HEX>"],
  // 큰 숫자 (4자리 이상)
  [/\b\d{4,}\b/g, "<NUM>"]
];
var normalizeLine = (line) => {
  let normalized = line;
  for (const [pattern, replacement] of NORMALIZATION_RULES) {
    normalized = normalized.replace(pattern, replacement);
  }
  return normalized;
};
var deduplicateLines = (text) => {
  const lines = text.split("\n");
  const groups = /* @__PURE__ */ new Map();
  const orderedKeys = [];
  for (const line of lines) {
    if (line.trim().length === 0) {
      const emptyKey = `__EMPTY_${orderedKeys.length}__`;
      groups.set(emptyKey, { count: 1, originalLine: line });
      orderedKeys.push(emptyKey);
      continue;
    }
    const normalized = normalizeLine(line);
    if (groups.has(normalized)) {
      groups.get(normalized).count += 1;
    } else {
      groups.set(normalized, { count: 1, originalLine: line });
      orderedKeys.push(normalized);
    }
  }
  return orderedKeys.map((key) => {
    const group = groups.get(key);
    if (group.count > 1) {
      return `[x${group.count}] ${normalizeLine(group.originalLine)}`;
    }
    return group.originalLine;
  }).join("\n");
};

// src/platform/token-optimizer/optimize.ts
var optimizeText = (text, options = {}) => {
  const originalTokens = countTokens(text);
  if (!text) {
    return { text: "", originalTokens: 0, optimizedTokens: 0, savingsPercent: 0 };
  }
  const {
    stripAnsi: shouldStripAnsi = true,
    maxCharsPerLine,
    maxLines,
    headLines,
    tailLines,
    deduplicate = false,
    keepPatterns,
    stripPatterns,
    stripEmptyLines = true
  } = options;
  let result = shouldStripAnsi ? stripAnsi(text) : text;
  const hasFilterOptions = keepPatterns && keepPatterns.length > 0 || stripPatterns && stripPatterns.length > 0 || stripEmptyLines;
  if (hasFilterOptions) {
    result = filterLines(result, { keepPatterns, stripPatterns, stripEmptyLines });
  }
  if (deduplicate) {
    result = deduplicateLines(result);
  }
  const hasTruncateOptions = maxCharsPerLine !== void 0 || maxLines !== void 0 || headLines !== void 0 || tailLines !== void 0;
  if (hasTruncateOptions) {
    result = truncateLines(result, { maxCharsPerLine, maxLines, headLines, tailLines });
  }
  const optimizedTokens = countTokens(result);
  const savingsPercent = originalTokens > 0 ? Math.round((1 - optimizedTokens / originalTokens) * 1e3) / 10 : 0;
  return {
    text: result,
    originalTokens,
    optimizedTokens,
    savingsPercent
  };
};
function createPromptHistoryReferenceSection(historyReferences) {
  if (!historyReferences) {
    return void 0;
  }
  return {
    heading: "\uD788\uC2A4\uD1A0\uB9AC \uCC38\uC870",
    markdown: [
      "- \uD604\uC7AC \uC694\uCCAD\uC774 \uC774\uC804 \uC791\uC5C5\uC758 \uC5F0\uC7A5, \uC218\uC815, \uD6C4\uC18D \uC9C8\uBB38, \uC0DD\uB7B5\uB41C \uB9E5\uB77D \uBCF5\uC6D0\uCC98\uB7FC \uBCF4\uC774\uBA74 \uC0AC\uC6A9\uC790\uAC00 \uBA85\uC2DC\uD558\uC9C0 \uC54A\uC544\uB3C4 \uBA3C\uC800 \uC544\uB798 \uD788\uC2A4\uD1A0\uB9AC\uB97C \uD655\uC778\uD55C\uB2E4.",
      '- \uC0AC\uC6A9\uC790\uAC00 "\uC774\uC804", "\uBC29\uAE08", "\uC544\uAE4C", "\uACC4\uC18D", "\uADF8\uAC70", "\uADF8 \uBC29\uC2DD", "\uAC19\uC740 \uAE30\uC900"\uCC98\uB7FC \uAE30\uC874 \uB9E5\uB77D\uC744 \uC554\uC2DC\uD558\uBA74 \uC6B0\uC120\uC801\uC73C\uB85C \uD788\uC2A4\uD1A0\uB9AC\uB97C \uC870\uD68C\uD55C\uB2E4.',
      "- \uC694\uCCAD\uB9CC\uC73C\uB85C\uB294 \uC548\uC804\uD55C \uAD6C\uD604 \uACB0\uC815\uC744 \uB0B4\uB9AC\uAE30 \uC5B4\uB835\uAC70\uB098, \uAE30\uC874 \uACB0\uC815/\uC0B0\uCD9C\uBB3C/\uC2E4\uD328 \uC6D0\uC778\uC744 \uC7AC\uC0AC\uC6A9\uD574\uC57C \uD558\uBA74 \uB0B4\uBD80 \uD310\uB2E8\uC73C\uB85C \uD788\uC2A4\uD1A0\uB9AC\uB97C \uBA3C\uC800 \uD655\uC778\uD55C\uB2E4.",
      "- AI\uC758 \uC804\uCCB4 \uD788\uC2A4\uD1A0\uB9AC\uB97C \uC870\uD68C/\uCC38\uC870\uD574\uC57C \uD558\uB294 \uACBD\uC6B0 \uC544\uB798 \uB514\uB809\uD130\uB9AC\uB97C \uC9C1\uC811 \uD655\uC778\uD55C\uB2E4.",
      `- \uC804\uCCB4 AI \uD788\uC2A4\uD1A0\uB9AC \uB514\uB809\uD130\uB9AC: \`${path3__default.default.normalize(historyReferences.aiHistoryDirectoryPath)}\``,
      "- \uC0AC\uC6A9\uC790\uAC00 \uC791\uC131\uD55C \uD504\uB86C\uD504\uD2B8 \uB0B4\uC5ED\uB9CC \uD544\uC694\uD55C \uACBD\uC6B0 \uC544\uB798 \uD30C\uC77C\uC744 \uC9C1\uC811 \uD655\uC778\uD55C\uB2E4.",
      `- \uC0AC\uC6A9\uC790 \uD504\uB86C\uD504\uD2B8 \uD788\uC2A4\uD1A0\uB9AC \uD30C\uC77C: \`${path3__default.default.normalize(historyReferences.promptHistoryFilePath)}\``,
      "- \uD504\uB86C\uD504\uD2B8 \uBCF8\uBB38\uC5D0\uB294 \uACFC\uAC70 \uD788\uC2A4\uD1A0\uB9AC \uB0B4\uC6A9\uC744 \uC9C1\uC811 \uB2E4\uC2DC \uC2E3\uC9C0 \uB9D0\uACE0, \uD544\uC694\uD560 \uB54C \uC704 \uACBD\uB85C\uB97C \uCC38\uC870\uD574 \uBB38\uB9E5\uC744 \uBCF5\uC6D0\uD55C \uB4A4 \uC791\uC5C5\uD55C\uB2E4."
    ].join("\n")
  };
}
function isPromptMarkdownFileReference(asset) {
  return typeof asset !== "string";
}

// src/platform/prompts/render.ts
var TOKEN_OPTIMIZER_PRESET_BY_MODE = {
  chat: {
    stripAnsi: true
  },
  commit: {
    maxCharsPerLine: 400,
    stripAnsi: true,
    stripEmptyLines: true
  },
  "gen-html": {
    stripAnsi: true
  },
  "gen-storybook": {
    stripAnsi: true
  },
  "minify-md": {
    stripAnsi: true
  },
  "talk-to-figma": {
    stripAnsi: true
  },
  review: {
    maxCharsPerLine: 400,
    stripAnsi: true,
    stripEmptyLines: true
  }
};
var COMPACT_WORKSPACE_LIMITS = {
  commit: {
    diffStatLines: 20,
    statusLines: 24
  }
};
function normalizeMarkdown(markdown) {
  return markdown.trim();
}
function renderMarkdownAssetBlocks(markdownAssets) {
  const assets = markdownAssets || [];
  const inlineMarkdownBlocks = assets.filter((asset) => typeof asset === "string").map(normalizeMarkdown).filter(Boolean);
  const fileReferenceBlocks = assets.filter(isPromptMarkdownFileReference).map((asset) => `- \`${asset.filePath.trim()}\``);
  const blocks = [
    inlineMarkdownBlocks.length > 0 ? inlineMarkdownBlocks.join("\n\n") : "",
    fileReferenceBlocks.length > 0 ? fileReferenceBlocks.join("\n") : ""
  ].filter(Boolean);
  if (blocks.length === 0) {
    return "";
  }
  return blocks.join("\n\n");
}
function renderLabeledSection(section) {
  const markdown = normalizeMarkdown(section.markdown);
  if (!markdown) {
    return "";
  }
  return [`[${section.heading}]`, markdown].join("\n");
}
function buildExecutionOptionsSection(prompt) {
  return {
    heading: "\uC2E4\uD589 \uC635\uC158",
    markdown: [
      `- autoYes: ${prompt.autoYes ? "yes" : "no"}`,
      prompt.autoYes ? "- \uAD8C\uD55C \uC694\uCCAD\uC740 \uBCC4\uB3C4 \uD655\uC778 \uC5C6\uC774 yes \uB85C \uCC98\uB9AC\uD55C\uB2E4." : "- \uAD8C\uD55C \uC694\uCCAD\uC740 \uC11C\uBE44\uC2A4 \uAE30\uBCF8 \uC2B9\uC778 \uC815\uCC45\uC744 \uB530\uB978\uB2E4."
    ].join("\n")
  };
}
function limitLines(lines, maxLines) {
  if (lines.length <= maxLines) {
    return lines;
  }
  return [...lines.slice(0, maxLines), `... (${lines.length - maxLines}\uC904 \uC0DD\uB7B5)`];
}
function renderWorkspaceSnapshotMarkdown(prompt) {
  return prompt.workspaceSnapshot.available ? [
    `Git Root: ${prompt.workspaceSnapshot.gitRoot}`,
    `Branch: ${prompt.workspaceSnapshot.branch || "(detached)"}`,
    "",
    "[git status --short]",
    prompt.workspaceSnapshot.statusLines.join("\n") || "(\uC5C6\uC74C)",
    "",
    "[git diff --stat]",
    prompt.workspaceSnapshot.diffStat || "(\uC5C6\uC74C)",
    "",
    "[\uCD5C\uADFC \uCEE4\uBC0B]",
    prompt.workspaceSnapshot.recentCommits.join("\n") || "(\uC5C6\uC74C)"
  ].join("\n") : prompt.workspaceSnapshot.note;
}
function renderCompactWorkspaceSnapshotMarkdown(prompt, mode) {
  if (!prompt.workspaceSnapshot.available) {
    return "";
  }
  if (mode === "review" || mode === "gen-html" || mode === "gen-storybook" || mode === "minify-md" || mode === "talk-to-figma") {
    return "";
  }
  if (mode === "commit") {
    const compactStatusLines = limitLines(
      prompt.workspaceSnapshot.statusLines,
      COMPACT_WORKSPACE_LIMITS.commit.statusLines
    );
    const compactDiffStatLines = limitLines(
      prompt.workspaceSnapshot.diffStat.split("\n").filter(Boolean),
      COMPACT_WORKSPACE_LIMITS.commit.diffStatLines
    );
    return [
      `- Branch: ${prompt.workspaceSnapshot.branch || "(detached)"}`,
      "",
      "[\uBCC0\uACBD \uD30C\uC77C \uC0C1\uD0DC]",
      compactStatusLines.join("\n") || "(\uC5C6\uC74C)",
      "",
      "[\uBCC0\uACBD \uC694\uC57D]",
      compactDiffStatLines.join("\n") || "(\uC5C6\uC74C)"
    ].join("\n");
  }
  return renderWorkspaceSnapshotMarkdown(prompt);
}
function shouldUseCompactStructuredRender(mode) {
  return !!mode && mode !== "chat";
}
function toPromptSections(prompt, options = {}) {
  const historyReferenceSection = createPromptHistoryReferenceSection(prompt.historyReferences);
  const workspaceMarkdown = options.compact ? renderCompactWorkspaceSnapshotMarkdown(prompt, options.mode) : renderWorkspaceSnapshotMarkdown(prompt);
  const sections = [
    ...options.compact ? [] : [buildExecutionOptionsSection(prompt)],
    {
      heading: "\uC9C0\uCE68 - \uBC18\uB4DC\uC2DC \uC77D\uACE0 \uADF8\uB300\uB85C \uC9C0\uCF1C\uC57C\uD560\uAC83",
      markdown: renderMarkdownAssetBlocks(prompt.instructions)
    },
    ...historyReferenceSection ? [historyReferenceSection] : [],
    ...normalizeMarkdown(workspaceMarkdown) ? [
      {
        heading: "\uD604\uC7AC \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uC0C1\uD0DC",
        markdown: workspaceMarkdown
      }
    ] : [],
    {
      heading: "\uADDC\uCE59 - \uC774\uD558 \uB0B4\uC6A9\uC774 \uC5C6\uC73C\uBA74 \uBB34\uC2DC\uD558\uACE0, \uC801\uC6A9\uC5EC\uBD80\uB098 \uC801\uC6A9\uC870\uAC74\uC740 [\uC9C0\uCE68]\uC758 \uB0B4\uC6A9\uC744 \uB530\uB978\uB2E4.",
      markdown: renderMarkdownAssetBlocks(prompt.rules)
    },
    {
      heading: "\uC751\uB2F5 \uC591\uC2DD  - \uC774\uD558 \uB0B4\uC6A9\uC774 \uC5C6\uC73C\uBA74 \uBB34\uC2DC\uD558\uACE0, \uC801\uC6A9\uC5EC\uBD80\uB098 \uC801\uC6A9\uC870\uAC74\uC740 [\uC9C0\uCE68]\uC758 \uB0B4\uC6A9\uC744 \uB530\uB978\uB2E4.",
      markdown: renderMarkdownAssetBlocks(prompt.forms)
    },
    ...prompt.sections || []
  ];
  return sections.filter((section) => normalizeMarkdown(section.markdown));
}
function renderStructuredPrompt(prompt, mode, compact = false) {
  return [
    `# ${prompt.title}`,
    ...compact ? [] : ["", `\uD604\uC7AC \uC120\uD0DD\uB41C AI \uC11C\uBE44\uC2A4: ${prompt.service}`],
    ...toPromptSections(prompt, { compact, mode }).flatMap((section) => ["", renderLabeledSection(section)])
  ].join("\n");
}
function getUtf8ByteLength(text) {
  return Buffer.byteLength(text, "utf8");
}
function buildPromptOptimizationAudit(mode, originalPrompt, optimizedPrompt) {
  const originalBytes = getUtf8ByteLength(originalPrompt);
  const optimizedBytes = getUtf8ByteLength(optimizedPrompt.text);
  const reducedBytes = originalBytes - optimizedBytes;
  const reductionPercent = originalBytes > 0 ? Math.round(reducedBytes / originalBytes * 1e3) / 10 : 0;
  const originalEstimatedTokens = countTokens(originalPrompt);
  const reducedEstimatedTokens = originalEstimatedTokens - optimizedPrompt.optimizedTokens;
  const tokenReductionPercent = originalEstimatedTokens > 0 ? Math.round(reducedEstimatedTokens / originalEstimatedTokens * 1e3) / 10 : 0;
  return {
    mode,
    optimizedBytes,
    optimizedEstimatedTokens: optimizedPrompt.optimizedTokens,
    optimizedPrompt: optimizedPrompt.text,
    originalBytes,
    originalEstimatedTokens,
    originalPrompt,
    reducedBytes,
    reducedEstimatedTokens,
    reductionPercent,
    tokenReductionPercent
  };
}
function optimizeRenderedPrompt(prompt, mode, originalPrompt) {
  if (!mode || !isTokenOptimizerEnabled()) {
    return {
      text: prompt
    };
  }
  const optimizedPrompt = optimizeText(prompt, TOKEN_OPTIMIZER_PRESET_BY_MODE[mode]);
  return {
    promptAudit: buildPromptOptimizationAudit(mode, originalPrompt || prompt, optimizedPrompt),
    text: optimizedPrompt.text
  };
}
function renderPromptForService(prompt, mode) {
  if (typeof prompt === "string") {
    return optimizeRenderedPrompt(safeExcerpt(prompt, 2e5), mode);
  }
  const originalPrompt = renderStructuredPrompt(prompt, mode, false);
  const shouldCompact = isTokenOptimizerEnabled() && shouldUseCompactStructuredRender(mode);
  const renderedPrompt = shouldCompact ? renderStructuredPrompt(prompt, mode, true) : originalPrompt;
  return optimizeRenderedPrompt(renderedPrompt, mode, originalPrompt);
}

exports.renderPromptForService = renderPromptForService;
