// Force strict mode and setup for ESM
"use strict";
import {
  createDebugLogger
} from "./chunk-7NFB7LBQ.js";
import {
  init_esbuild_shims
} from "./chunk-5O2XNYP6.js";
import {
  __name
} from "./chunk-J2S4EL5Y.js";

// packages/core/src/tools/skill-utils.ts
init_esbuild_shims();

// packages/core/src/utils/xml.ts
init_esbuild_shims();
function escapeXml(text) {
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
}
__name(escapeXml, "escapeXml");
var XML_TAG_CANDIDATE_RE = /<[^<>]*>/g;
function isXmlWhitespace(char) {
  return char !== void 0 && /\s/.test(char);
}
__name(isXmlWhitespace, "isXmlWhitespace");
function isSystemReminderTagIgnorable(char) {
  const codePoint = char.codePointAt(0);
  if (codePoint === void 0) return false;
  return codePoint === 173 || codePoint === 1564 || codePoint === 12644 || codePoint === 65279 || codePoint === 65440 || codePoint >= 0 && codePoint <= 31 || codePoint >= 127 && codePoint <= 159 || codePoint >= 4447 && codePoint <= 4448 || codePoint >= 6068 && codePoint <= 6069 || codePoint >= 6155 && codePoint <= 6159 || codePoint >= 8203 && codePoint <= 8207 || codePoint >= 8234 && codePoint <= 8238 || codePoint >= 8288 && codePoint <= 8303 || codePoint >= 65024 && codePoint <= 65039 || codePoint >= 65520 && codePoint <= 65528 || codePoint >= 113824 && codePoint <= 113827 || codePoint >= 119155 && codePoint <= 119162 || codePoint >= 917504 && codePoint <= 921599;
}
__name(isSystemReminderTagIgnorable, "isSystemReminderTagIgnorable");
function normalizeSystemReminderCandidateTag(tag) {
  let normalized = "";
  for (const char of tag) {
    if (!isSystemReminderTagIgnorable(char)) {
      normalized += char;
    }
  }
  return normalized.toLowerCase();
}
__name(normalizeSystemReminderCandidateTag, "normalizeSystemReminderCandidateTag");
function getSystemReminderTagKind(tag) {
  const normalized = normalizeSystemReminderCandidateTag(tag);
  const len = normalized.length;
  if (len < 2 || normalized[0] !== "<" || normalized[len - 1] !== ">") {
    return void 0;
  }
  let i = 1;
  while (i < len && isXmlWhitespace(normalized[i])) i++;
  let closing = false;
  if (normalized[i] === "/") {
    closing = true;
    i++;
  }
  while (i < len && isXmlWhitespace(normalized[i])) i++;
  const TAG_NAME = "system-reminder";
  if (normalized.slice(i, i + TAG_NAME.length) !== TAG_NAME) {
    return void 0;
  }
  i += TAG_NAME.length;
  if (i < len - 1 && isXmlWhitespace(normalized[i])) {
    while (i < len && isXmlWhitespace(normalized[i])) i++;
    while (i < len && normalized[i] !== ">") i++;
  }
  while (i < len && isXmlWhitespace(normalized[i])) i++;
  if (normalized[i] === "/") i++;
  while (i < len && isXmlWhitespace(normalized[i])) i++;
  if (i !== len - 1 || normalized[i] !== ">") {
    return void 0;
  }
  return closing ? "closing" : "other";
}
__name(getSystemReminderTagKind, "getSystemReminderTagKind");
function escapeSystemReminderTag(tag) {
  const tagKind = getSystemReminderTagKind(tag);
  if (tagKind === "closing") {
    return "<\\/system-reminder>";
  }
  if (tagKind === "other") {
    return escapeXml(tag);
  }
  return tag;
}
__name(escapeSystemReminderTag, "escapeSystemReminderTag");
function escapeSystemReminderTags(text) {
  return text.replace(XML_TAG_CANDIDATE_RE, escapeSystemReminderTag);
}
__name(escapeSystemReminderTags, "escapeSystemReminderTags");

// packages/core/src/tools/skill-utils.ts
function buildSkillLlmContent(baseDir, body) {
  return `Base directory for this skill: ${baseDir}
Important: ALWAYS resolve absolute paths from this base directory when working with skills.

${body}
`;
}
__name(buildSkillLlmContent, "buildSkillLlmContent");
var collectCache = /* @__PURE__ */ new WeakMap();
var COLLECT_CACHE_TTL_MS = 2e3;
function clearCollectedSkillEntriesCache(skillManager) {
  if (skillManager) {
    collectCache.delete(skillManager);
  } else {
    collectCache = /* @__PURE__ */ new WeakMap();
  }
}
__name(clearCollectedSkillEntriesCache, "clearCollectedSkillEntriesCache");
async function collectAvailableSkillEntries(skillManager, config) {
  const cached = collectCache.get(skillManager);
  if (cached && Date.now() - cached.ts < COLLECT_CACHE_TTL_MS) {
    return cached.promise;
  }
  const promise = collectAvailableSkillEntriesUncached(skillManager, config);
  collectCache.set(skillManager, { promise, ts: Date.now() });
  promise.catch(() => {
    const entry = collectCache.get(skillManager);
    if (entry?.promise === promise) {
      collectCache.delete(skillManager);
    }
  });
  return promise;
}
__name(collectAvailableSkillEntries, "collectAvailableSkillEntries");
async function collectAvailableSkillEntriesUncached(skillManager, config) {
  const allSkills = await skillManager.listSkills();
  const disabledNames = config.getDisabledSkillNames();
  const isDisabled = /* @__PURE__ */ __name((name) => disabledNames.has(name.toLowerCase()), "isDisabled");
  const availableSkills = allSkills.filter(
    (s) => !s.disableModelInvocation && skillManager.isSkillActive(s) && !isDisabled(s.name)
  );
  const pendingConditionalSkillNames = new Set(
    allSkills.filter(
      (s) => !s.disableModelInvocation && s.paths && s.paths.length > 0 && !skillManager.isSkillActive(s) && !isDisabled(s.name)
    ).map((s) => s.name)
  );
  const provider = config.getModelInvocableCommandsProvider();
  const allCommands = provider ? provider() : [];
  const fileBasedSkillNames = new Set(
    allSkills.filter((s) => !s.disableModelInvocation && !isDisabled(s.name)).map((s) => s.name)
  );
  const modelInvocableCommands = allCommands.filter(
    (cmd) => !fileBasedSkillNames.has(cmd.name)
  );
  const entries = [
    ...availableSkills.map((s) => ({
      name: s.name,
      description: s.description,
      whenToUse: s.whenToUse,
      level: s.level
    })),
    ...modelInvocableCommands.map((c) => ({
      name: c.name,
      description: c.description
    }))
  ];
  return {
    availableSkills,
    pendingConditionalSkillNames,
    modelInvocableCommands,
    entries
  };
}
__name(collectAvailableSkillEntriesUncached, "collectAvailableSkillEntriesUncached");
function compareSkillEntries(a, b) {
  const aGroup = a.level !== void 0 ? 0 : 1;
  const bGroup = b.level !== void 0 ? 0 : 1;
  if (aGroup !== bGroup) return aGroup - bGroup;
  return a.name.localeCompare(b.name);
}
__name(compareSkillEntries, "compareSkillEntries");
function renderAvailableSkillsBlock(entries) {
  return [...entries].sort(compareSkillEntries).map((entry) => {
    if (entry.level !== void 0) {
      const descText = `${escapeXml(entry.description)}${entry.whenToUse ? ` \u2014 ${escapeXml(entry.whenToUse)}` : ""} (${entry.level})`;
      return `<skill>
<name>
${escapeXml(entry.name)}
</name>
<description>
${descText}
</description>
<location>
${entry.level}
</location>
</skill>`;
    }
    return `<skill>
<name>
${escapeXml(entry.name)}
</name>
<description>
${escapeXml(entry.description)}
</description>
</skill>`;
  }).join("\n");
}
__name(renderAvailableSkillsBlock, "renderAvailableSkillsBlock");
function applySkillAllowedTools(permissionManager, allowedTools) {
  if (!permissionManager || !allowedTools?.length) {
    return;
  }
  for (const rule of allowedTools) {
    permissionManager.addSessionAllowRule(rule);
  }
}
__name(applySkillAllowedTools, "applySkillAllowedTools");

// packages/core/src/hooks/registerSkillHooks.ts
init_esbuild_shims();
var debugLogger = createDebugLogger("SKILL_HOOKS");
function registerSkillHooks(sessionHooksManager, sessionId, skill) {
  if (!skill.hooks) {
    debugLogger.debug(`Skill '${skill.name}' has no hooks to register`);
    return 0;
  }
  const hooksSettings = skill.hooks;
  let registeredCount = 0;
  for (const eventName of Object.keys(hooksSettings)) {
    const matchers = hooksSettings[eventName];
    if (!matchers) continue;
    for (const matcher of matchers) {
      const matcherPattern = matcher.matcher || "";
      for (const hook of matcher.hooks) {
        if (hook.type === "function" /* Function */) {
          debugLogger.debug(
            "Skipping function hook from skill (not supported in frontmatter)"
          );
          continue;
        }
        const hookConfig = prepareHookConfig(
          hook,
          skill.skillRoot
        );
        sessionHooksManager.addSessionHook(
          sessionId,
          eventName,
          matcherPattern,
          hookConfig,
          { skillRoot: skill.skillRoot }
        );
        registeredCount++;
        debugLogger.debug(
          `Registered hook for ${eventName} with matcher '${matcherPattern}' from skill '${skill.name}'`
        );
      }
    }
  }
  if (registeredCount > 0) {
    debugLogger.info(
      `Registered ${registeredCount} hooks from skill '${skill.name}'`
    );
  }
  return registeredCount;
}
__name(registerSkillHooks, "registerSkillHooks");
function prepareHookConfig(hook, skillRoot) {
  if (hook.type === "command" && skillRoot) {
    return {
      ...hook,
      env: {
        ...hook.env,
        QWEN_SKILL_ROOT: skillRoot
      }
    };
  }
  return hook;
}
__name(prepareHookConfig, "prepareHookConfig");

export {
  escapeXml,
  escapeSystemReminderTags,
  buildSkillLlmContent,
  clearCollectedSkillEntriesCache,
  collectAvailableSkillEntries,
  renderAvailableSkillsBlock,
  applySkillAllowedTools,
  registerSkillHooks
};
/**
 * @license
 * Copyright 2025 Qwen
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2026 Qwen Team
 * SPDX-License-Identifier: Apache-2.0
 */
