@axis-ds/mcp 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +290 -84
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -41,7 +41,7 @@ Claude Desktop 또는 기타 MCP 호환 클라이언트에서 설정:
41
41
  - 이름은 레지스트리 이름 그대로입니다. Agentic UI 는 `agentic-` 접두를 붙입니다(예: `agentic-run-progress`). 의존 항목(`utils` · `agentic-a11y-labels`)은 함께 설치됩니다.
42
42
  - `targetDir` 는 이미 있는 프로젝트 루트입니다(상대 경로는 서버의 현재 디렉터리 기준). `axis.config.json` 이 있으면 그 `componentsDir` · `agenticDir` 에, 없으면 `components/ui` · `components/agentic` 에 설치하고 그 사실을 알립니다. 프로젝트 밖으로 나가는 경로는 아무것도 쓰지 않고 실패합니다.
43
43
  - 내용이 다른 기존 파일은 덮어쓰지 않고 건너뛰며 응답 첫머리에 건너뛴 수를 적습니다. `overwrite: true` 일 때만 덮어씁니다.
44
- - 의존성은 설치하지 않고 lockfile 에 맞는 명령(`pnpm add` · `npm install` · `yarn add`)만 안내합니다.
44
+ - 의존성은 설치하지 않고 lockfile 에 맞는 명령(`pnpm add` · `npm install` · `yarn add`)만 안내합니다. lockfile 이 없으면 `package.json` 의 `packageManager` 를 봅니다(1.4.2 부터). `axis.apply_template` 의 「필요한 의존성」 · `axis.list_brands` · `axis.get_brand` 의 설치 안내도 1.4.2 부터 같은 방식으로 `targetDir` 의 매니저를 따릅니다(1.4.1 까지는 `pnpm` 고정).
45
45
 
46
46
  ## 토큰 도구
47
47
 
package/dist/index.js CHANGED
@@ -603,7 +603,7 @@ function createPinnedFetch(options = {}) {
603
603
  const judge = options.judge ?? blockedAddressReason;
604
604
  const send = options.request ?? httpsRequest;
605
605
  const maxBytes = options.maxBytes ?? PINNED_FETCH_MAX_BYTES;
606
- return (input, init) => new Promise((resolve5, reject) => {
606
+ return (input, init) => new Promise((resolve4, reject) => {
607
607
  let url;
608
608
  try {
609
609
  url = new URL(input);
@@ -644,7 +644,7 @@ function createPinnedFetch(options = {}) {
644
644
  if (failed) return;
645
645
  const body = Buffer.concat(chunks).toString("utf8");
646
646
  const status = res.statusCode ?? 0;
647
- resolve5({ ok: status >= 200 && status < 300, status, text: async () => body });
647
+ resolve4({ ok: status >= 200 && status < 300, status, text: async () => body });
648
648
  });
649
649
  }
650
650
  );
@@ -871,14 +871,85 @@ var RegistryClient = class {
871
871
  };
872
872
 
873
873
  // ../axis-registry-core/src/project.ts
874
- import { existsSync as existsSync2, readFileSync as readFileSync3, statSync } from "fs";
874
+ import { existsSync as existsSync2, readFileSync as readFileSync3, realpathSync, statSync } from "fs";
875
875
  import path3 from "path";
876
- function detectInstallCommand(baseDir) {
877
- if (existsSync2(path3.join(baseDir, "pnpm-lock.yaml"))) return "pnpm install";
878
- if (existsSync2(path3.join(baseDir, "yarn.lock"))) return "yarn install";
879
- if (existsSync2(path3.join(baseDir, "package-lock.json"))) return "npm install";
876
+ function resolveBaseDir(baseDirInput) {
877
+ const resolved = path3.resolve(baseDirInput);
878
+ try {
879
+ return realpathSync(resolved);
880
+ } catch {
881
+ return resolved;
882
+ }
883
+ }
884
+ var LOCKFILE_COMMANDS = [
885
+ ["pnpm-lock.yaml", "pnpm install"],
886
+ ["yarn.lock", "yarn install"],
887
+ ["package-lock.json", "npm install"]
888
+ ];
889
+ function lockfileCommandAt(dir) {
890
+ return LOCKFILE_COMMANDS.find(([file]) => existsSync2(path3.join(dir, file)))?.[1];
891
+ }
892
+ function isWorkspaceRootDir(dir) {
893
+ if (isFile(path3.join(dir, "pnpm-workspace.yaml"))) return true;
894
+ let parsed;
895
+ try {
896
+ parsed = JSON.parse(readFileSync3(path3.join(dir, "package.json"), "utf8"));
897
+ } catch {
898
+ return false;
899
+ }
900
+ if (!isPlainObject(parsed)) return false;
901
+ const ws = parsed.workspaces;
902
+ return Array.isArray(ws) || isPlainObject(ws) && Array.isArray(ws.packages);
903
+ }
904
+ function findWorkspaceRoot(baseDirInput) {
905
+ let dir = resolveBaseDir(baseDirInput);
906
+ for (; ; ) {
907
+ if (isWorkspaceRootDir(dir)) return dir;
908
+ if (existsSync2(path3.join(dir, ".git"))) return void 0;
909
+ const parent = path3.dirname(dir);
910
+ if (parent === dir) return void 0;
911
+ dir = parent;
912
+ }
913
+ }
914
+ var PACKAGE_MANAGER_COMMANDS = {
915
+ pnpm: "pnpm install",
916
+ yarn: "yarn install",
917
+ npm: "npm install"
918
+ };
919
+ function packageManagerCommandAt(dir) {
920
+ let parsed;
921
+ try {
922
+ parsed = JSON.parse(readFileSync3(path3.join(dir, "package.json"), "utf8"));
923
+ } catch {
924
+ return void 0;
925
+ }
926
+ if (!isPlainObject(parsed) || typeof parsed.packageManager !== "string") return void 0;
927
+ const name = /^(pnpm|yarn|npm)@/.exec(parsed.packageManager.trim())?.[1];
928
+ return name !== void 0 ? PACKAGE_MANAGER_COMMANDS[name] : void 0;
929
+ }
930
+ function detectInstallCommand(baseDirInput) {
931
+ const baseDir = resolveBaseDir(baseDirInput);
932
+ const own = lockfileCommandAt(baseDir);
933
+ if (own !== void 0) return own;
934
+ const found = findWorkspaceRoot(baseDir);
935
+ const root = found !== void 0 && found !== baseDir ? found : void 0;
936
+ if (root !== void 0) {
937
+ const fromRoot = lockfileCommandAt(root);
938
+ if (fromRoot !== void 0) return fromRoot;
939
+ }
940
+ const ownManager = packageManagerCommandAt(baseDir);
941
+ if (ownManager !== void 0) return ownManager;
942
+ if (root !== void 0) {
943
+ const rootManager = packageManagerCommandAt(root);
944
+ if (rootManager !== void 0) return rootManager;
945
+ }
880
946
  return "pnpm install";
881
947
  }
948
+ function packageManagerOf(command) {
949
+ if (command.startsWith("yarn")) return "yarn";
950
+ if (command.startsWith("npm")) return "npm";
951
+ return "pnpm";
952
+ }
882
953
  function hasDependency(pkg, name) {
883
954
  for (const field of ["dependencies", "devDependencies"]) {
884
955
  const deps = pkg[field];
@@ -888,14 +959,52 @@ function hasDependency(pkg, name) {
888
959
  }
889
960
  return void 0;
890
961
  }
962
+ function workspaceRootPackage(baseDirInput) {
963
+ const baseDir = resolveBaseDir(baseDirInput);
964
+ const root = findWorkspaceRoot(baseDir);
965
+ if (root === void 0 || root === baseDir) return void 0;
966
+ try {
967
+ const parsed = JSON.parse(readFileSync3(path3.join(root, "package.json"), "utf8"));
968
+ return isPlainObject(parsed) ? parsed : void 0;
969
+ } catch {
970
+ return void 0;
971
+ }
972
+ }
973
+ function declaredDependency(baseDir, pkg, name, rootPkg) {
974
+ if (pkg === void 0) return void 0;
975
+ const own = hasDependency(pkg, name);
976
+ if (own !== void 0) return { range: own, source: "app" };
977
+ const root = rootPkg === void 0 ? workspaceRootPackage(baseDir) : rootPkg ?? void 0;
978
+ const fromRoot = root !== void 0 ? hasDependency(root, name) : void 0;
979
+ return fromRoot !== void 0 ? { range: fromRoot, source: "root" } : void 0;
980
+ }
891
981
  function isPlainObject(value) {
892
982
  return typeof value === "object" && value !== null && !Array.isArray(value);
893
983
  }
894
- function addCommandFor(installCommand, deps) {
984
+ function addCommandPrefix(installCommand, options = {}) {
985
+ const dev = options.dev ? " -D" : "";
986
+ switch (packageManagerOf(installCommand)) {
987
+ case "yarn":
988
+ return `yarn add${dev}`;
989
+ case "npm":
990
+ return `npm install${dev}`;
991
+ default:
992
+ return `pnpm add${dev}`;
993
+ }
994
+ }
995
+ function addCommandFor(installCommand, deps, options = {}) {
895
996
  const specs = Object.entries(deps).map(([name, range]) => `"${name}@${range}"`).join(" ");
896
- if (installCommand.startsWith("yarn")) return `yarn add ${specs}`;
897
- if (installCommand.startsWith("npm")) return `npm install ${specs}`;
898
- return `pnpm add ${specs}`;
997
+ return `${addCommandPrefix(installCommand, options)} ${specs}`;
998
+ }
999
+ function workspaceRunCommand(installCommand, pkg, script) {
1000
+ switch (packageManagerOf(installCommand)) {
1001
+ case "yarn":
1002
+ return `yarn workspace ${pkg} ${script}`;
1003
+ case "npm":
1004
+ return `npm run ${script} -w ${pkg}`;
1005
+ default:
1006
+ return `pnpm --filter ${pkg} ${script}`;
1007
+ }
899
1008
  }
900
1009
  var GLOBAL_CSS_CANDIDATES = [
901
1010
  "app/globals.css",
@@ -934,7 +1043,7 @@ function exactVersionOf(version) {
934
1043
  return v;
935
1044
  }
936
1045
  function findInstalledPackage(baseDirInput, name) {
937
- let dir = path3.resolve(baseDirInput);
1046
+ let dir = resolveBaseDir(baseDirInput);
938
1047
  for (; ; ) {
939
1048
  const pkgDir = path3.join(dir, "node_modules", ...name.split("/"));
940
1049
  const file = path3.join(pkgDir, "package.json");
@@ -954,7 +1063,7 @@ function findInstalledPackage(baseDirInput, name) {
954
1063
  }
955
1064
  }
956
1065
  function isPnpProject(baseDirInput) {
957
- let dir = path3.resolve(baseDirInput);
1066
+ let dir = resolveBaseDir(baseDirInput);
958
1067
  for (; ; ) {
959
1068
  if (isFile(path3.join(dir, ".pnp.cjs")) || isFile(path3.join(dir, ".pnp.js"))) return true;
960
1069
  const parent = path3.dirname(dir);
@@ -975,16 +1084,10 @@ function compareExactVersions(a, b) {
975
1084
  }
976
1085
 
977
1086
  // ../axis-registry-core/src/template/tailwind-core.ts
978
- import { existsSync as existsSync3, lstatSync, readdirSync, readFileSync as readFileSync4 } from "fs";
979
- import { extname, join as join2, resolve } from "path";
980
- function hasDependency2(pkg, name) {
981
- for (const field of ["dependencies", "devDependencies"]) {
982
- const deps = pkg[field];
983
- if (typeof deps === "object" && deps !== null && name in deps) {
984
- return String(deps[name]);
985
- }
986
- }
987
- return void 0;
1087
+ import { existsSync as existsSync3, lstatSync, readdirSync, readFileSync as readFileSync4, realpathSync as realpathSync2 } from "fs";
1088
+ import { basename, dirname as dirname2, extname, isAbsolute, join as join2, relative, resolve, sep } from "path";
1089
+ function declaredRange(baseDir, pkg, name) {
1090
+ return declaredDependency(baseDir, pkg, name)?.range;
988
1091
  }
989
1092
  function isPlainObject2(value) {
990
1093
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1057,8 +1160,8 @@ function majorFromVersion(version) {
1057
1160
  return Number(m[1]);
1058
1161
  }
1059
1162
  function detectTailwind(baseDirInput, pkg) {
1060
- const baseDir = resolve(baseDirInput);
1061
- const declared = pkg ? hasDependency2(pkg, "tailwindcss") : void 0;
1163
+ const baseDir = resolveBaseDir(baseDirInput);
1164
+ const declared = pkg ? declaredRange(baseDir, pkg, "tailwindcss") : void 0;
1062
1165
  const bounds = declared !== void 0 ? tailwindMajorBounds(declared) : void 0;
1063
1166
  const declaredMajor = bounds?.lower;
1064
1167
  const version = isPnpProject(baseDir) ? void 0 : findInstalledPackage(baseDir, "tailwindcss")?.version;
@@ -1109,7 +1212,7 @@ function findTokensCssImport(css) {
1109
1212
  var TOKENS_CSS_JS_IMPORT = /(?:\bimport\s+|\bfrom\s+|\brequire\s*\(\s*)(["'])(@axis-ds\/tokens\/css(?:\/shadcn|\/tailwind4)?)\1/;
1110
1213
  var AXIS_VARIABLE_DEFINITION = /(?<![\w-])--axis-[\w-]+\s*:/;
1111
1214
  function findLayoutTokensCssImport(baseDirInput) {
1112
- const baseDir = resolve(baseDirInput);
1215
+ const baseDir = resolveBaseDir(baseDirInput);
1113
1216
  for (const candidate of ROOT_LAYOUT_FILES) {
1114
1217
  const file = join2(baseDir, candidate);
1115
1218
  if (!existsSync3(file)) continue;
@@ -1125,7 +1228,7 @@ function findLayoutTokensCssImport(baseDirInput) {
1125
1228
  return void 0;
1126
1229
  }
1127
1230
  function checkGlobalsCss(baseDirInput) {
1128
- const baseDir = resolve(baseDirInput);
1231
+ const baseDir = resolveBaseDir(baseDirInput);
1129
1232
  for (const candidate of TAILWIND_CSS_CANDIDATES) {
1130
1233
  const file = join2(baseDir, candidate);
1131
1234
  if (!existsSync3(file)) continue;
@@ -1217,11 +1320,11 @@ function installedAxisVersion(baseDir, name) {
1217
1320
  }
1218
1321
  function axisPackagesBelowTailwind4(pkg, baseDirInput) {
1219
1322
  if (!pkg) return [];
1220
- const baseDir = baseDirInput !== void 0 ? resolve(baseDirInput) : void 0;
1323
+ const baseDir = baseDirInput !== void 0 ? resolveBaseDir(baseDirInput) : void 0;
1221
1324
  const out = [];
1222
1325
  const min = lowerOf(TAILWIND4_MIN_AXIS_VERSION);
1223
1326
  for (const name of TAILWIND4_AXIS_PACKAGES) {
1224
- const range = hasDependency2(pkg, name);
1327
+ const range = baseDir !== void 0 ? declaredRange(baseDir, pkg, name) : hasDependency(pkg, name);
1225
1328
  if (range === void 0 || range.trim().startsWith("workspace:")) continue;
1226
1329
  const installed = baseDir !== void 0 ? installedAxisVersion(baseDir, name) : void 0;
1227
1330
  const installedLower = installed !== void 0 ? lowerOf(installed) : void 0;
@@ -1361,7 +1464,7 @@ function isCommonJsConfig(file, source) {
1361
1464
  return extname(file) === ".cjs" || /\bmodule\.exports\b/.test(source);
1362
1465
  }
1363
1466
  function packageVersionGate(baseDirInput, pkg, name, min) {
1364
- const baseDir = resolve(baseDirInput);
1467
+ const baseDir = resolveBaseDir(baseDirInput);
1365
1468
  if (!isPnpProject(baseDir)) {
1366
1469
  const installed = findInstalledPackage(baseDir, name)?.version;
1367
1470
  if (installed !== void 0) {
@@ -1369,7 +1472,7 @@ function packageVersionGate(baseDirInput, pkg, name, min) {
1369
1472
  if (cmp !== void 0) return { status: cmp >= 0 ? "ok" : "below", source: "installed", value: installed };
1370
1473
  }
1371
1474
  }
1372
- const declared = pkg ? hasDependency2(pkg, name) : void 0;
1475
+ const declared = pkg ? declaredRange(baseDir, pkg, name) : void 0;
1373
1476
  if (declared !== void 0) {
1374
1477
  const atLeast = rangeLowerAtLeast(declared, min);
1375
1478
  if (atLeast !== void 0) return { status: atLeast ? "ok" : "below", source: "declared", value: declared };
@@ -1390,12 +1493,12 @@ function readPackageJson(baseDir) {
1390
1493
  return void 0;
1391
1494
  }
1392
1495
  }
1393
- function tailwind4Issues(css, pkg, versions) {
1496
+ function tailwind4Issues(css, pkg, versions, baseDir) {
1394
1497
  const issues = [];
1395
1498
  const hasEntry = hasTokensTailwind4Import(css);
1396
1499
  if (!hasEntry) issues.push(`AXIS \uD1A0\uD070 \uC9C4\uC785\uC810\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${TOKENS_TAILWIND4_IMPORT_LINE}`);
1397
1500
  const missing = TAILWIND4_COMPONENT_PACKAGES.filter(
1398
- (name) => pkg !== void 0 && hasDependency2(pkg, name) !== void 0 && !hasComponentTailwindImport(css, name) && !hasComponentSource(css, name)
1501
+ (name) => declaredRange(baseDir, pkg, name) !== void 0 && !hasComponentTailwindImport(css, name) && !hasComponentSource(css, name)
1399
1502
  );
1400
1503
  if (missing.length > 0) {
1401
1504
  issues.push(`\uCEF4\uD3EC\uB10C\uD2B8 \uC2A4\uCE94 \uACBD\uB85C(tailwind.css)\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2192 ${missing.map(componentTailwindImportLine).join(" ")}`);
@@ -1415,7 +1518,7 @@ function tailwind4Issues(css, pkg, versions) {
1415
1518
  return issues;
1416
1519
  }
1417
1520
  function checkTailwindSetup(baseDirInput) {
1418
- const baseDir = resolve(baseDirInput);
1521
+ const baseDir = resolveBaseDir(baseDirInput);
1419
1522
  const pkg = readPackageJson(baseDir);
1420
1523
  const tailwind = detectTailwind(baseDir, pkg);
1421
1524
  if (tailwind.major !== void 0 && tailwind.major >= 4) {
@@ -1432,7 +1535,7 @@ function checkTailwindSetup(baseDirInput) {
1432
1535
  };
1433
1536
  }
1434
1537
  const versions = axisPackagesBelowTailwind4(pkg, baseDir);
1435
- const issues = tailwind4Issues(css, pkg, versions);
1538
+ const issues = tailwind4Issues(css, pkg, versions, baseDir);
1436
1539
  if (issues.length > 0) {
1437
1540
  return {
1438
1541
  name: "tailwind.config",
@@ -1519,6 +1622,93 @@ function contentGlobToRegExp(glob) {
1519
1622
  }
1520
1623
  return new RegExp(`^${re}$`);
1521
1624
  }
1625
+ function leadingParentSegments(p) {
1626
+ const s = p.trim().replace(/\\/g, "/").replace(/^\.\//, "");
1627
+ return (/^(?:\.\.\/)*/.exec(s)?.[0].length ?? 0) / 3;
1628
+ }
1629
+ function isAbsoluteGlob(glob) {
1630
+ const t = glob.trim();
1631
+ return t.startsWith("/") || /^[A-Za-z]:[\\/]/.test(t);
1632
+ }
1633
+ var MAX_BRACE_EXPANSION = 256;
1634
+ function expandBraces(glob) {
1635
+ const open = glob.indexOf("{");
1636
+ if (open === -1) return [glob];
1637
+ let depth = 0;
1638
+ let close = -1;
1639
+ const commas = [];
1640
+ for (let i = open; i < glob.length; i++) {
1641
+ const c = glob[i];
1642
+ if (c === "{") depth++;
1643
+ else if (c === "}") {
1644
+ depth--;
1645
+ if (depth === 0) {
1646
+ close = i;
1647
+ break;
1648
+ }
1649
+ } else if (c === "," && depth === 1) commas.push(i);
1650
+ }
1651
+ const head = glob.slice(0, open + 1);
1652
+ if (close === -1 || commas.length === 0) {
1653
+ return expandBraces(glob.slice(open + 1))?.map((r) => head + r);
1654
+ }
1655
+ const parts = [];
1656
+ let from = open + 1;
1657
+ for (const c of [...commas, close]) {
1658
+ parts.push(glob.slice(from, c));
1659
+ from = c + 1;
1660
+ }
1661
+ const prefix = glob.slice(0, open);
1662
+ const suffix = glob.slice(close + 1);
1663
+ const out = [];
1664
+ for (const part of parts) {
1665
+ const expanded = expandBraces(prefix + part + suffix);
1666
+ if (expanded === void 0) return void 0;
1667
+ out.push(...expanded);
1668
+ if (out.length > MAX_BRACE_EXPANSION) return void 0;
1669
+ }
1670
+ return out;
1671
+ }
1672
+ function realpathPosix(p) {
1673
+ let cur = p;
1674
+ const tail = [];
1675
+ for (let i = 0; i < 64; i++) {
1676
+ try {
1677
+ return [realpathSync2(cur), ...tail].join(sep).split(sep).join("/");
1678
+ } catch {
1679
+ const parent = dirname2(cur);
1680
+ if (parent === cur) return void 0;
1681
+ tail.unshift(basename(cur));
1682
+ cur = parent;
1683
+ }
1684
+ }
1685
+ return void 0;
1686
+ }
1687
+ function contentGlobBranchCovers(glob, sample, baseDir) {
1688
+ if (isAbsoluteGlob(glob)) {
1689
+ const re = contentGlobToRegExp(glob.trim().replace(/\\/g, "/"));
1690
+ const absSample = resolve(baseDir, sample);
1691
+ if (re.test(absSample.split(sep).join("/"))) return true;
1692
+ const real = realpathPosix(absSample);
1693
+ return real !== void 0 && re.test(real);
1694
+ }
1695
+ return leadingParentSegments(glob) === leadingParentSegments(sample) && contentGlobToRegExp(glob).test(sample);
1696
+ }
1697
+ function contentGlobCovers(glob, sample, baseDirInput) {
1698
+ const baseDir = resolveBaseDir(baseDirInput);
1699
+ const branches = expandBraces(glob.trim()) ?? [glob];
1700
+ return branches.some((b) => contentGlobBranchCovers(b, sample, baseDir));
1701
+ }
1702
+ var CONTENT_PARENT_PATH_NOTE = "\uC0C1\uC704 \uACBD\uB85C\uB294 Tailwind 3 \uAC00 \uBE4C\uB4DC\uB97C \uC2E4\uD589\uD55C \uB514\uB809\uD130\uB9AC \uAE30\uC900\uC73C\uB85C \uD480\uB824\uC694. \uBAA8\uB178\uB808\uD3EC \uB8E8\uD2B8 \uB4F1 \uC571 \uB514\uB809\uD130\uB9AC \uBC16\uC5D0\uC11C \uBE4C\uB4DC\uD558\uBA74 content: { relative: true, files: [...] } \uB85C \uC124\uC815 \uD30C\uC77C \uAE30\uC900\uC73C\uB85C \uBC14\uAFB8\uC138\uC694";
1703
+ function packageContentTarget(baseDir, name) {
1704
+ const found = isPnpProject(baseDir) ? void 0 : findInstalledPackage(baseDir, name);
1705
+ const rel2 = found === void 0 ? void 0 : relative(baseDir, found.dir);
1706
+ const relDir = rel2 === void 0 || rel2 === "" || isAbsolute(rel2) ? `node_modules/${name}` : rel2.split(sep).join("/");
1707
+ return {
1708
+ sample: `${relDir}/dist/index.js`,
1709
+ suggest: `${relDir.startsWith("../") ? "" : "./"}${relDir}/dist/**/*.{js,mjs}`
1710
+ };
1711
+ }
1522
1712
  function balancedSlice(src, start) {
1523
1713
  const open = src[start];
1524
1714
  const close = open === "[" ? "]" : "}";
@@ -1566,7 +1756,7 @@ function normalizeRel(p) {
1566
1756
  return s;
1567
1757
  }
1568
1758
  function inspectTailwindContent(baseDirInput) {
1569
- const baseDir = resolve(baseDirInput);
1759
+ const baseDir = resolveBaseDir(baseDirInput);
1570
1760
  const pkg = readPackageJson(baseDir);
1571
1761
  const tailwind = detectTailwind(baseDir, pkg);
1572
1762
  if (tailwind.major !== void 0 && tailwind.major >= 4) return null;
@@ -1579,18 +1769,18 @@ function inspectTailwindContent(baseDirInput) {
1579
1769
  targets.push({ label: `componentsDir(${componentsDir})`, sample: `${rel2}/button.tsx`, suggest: `./${rel2}/**/*.{ts,tsx}` });
1580
1770
  }
1581
1771
  for (const name of TAILWIND4_COMPONENT_PACKAGES) {
1582
- if (pkg !== void 0 && hasDependency2(pkg, name) !== void 0) {
1583
- targets.push({ label: name, sample: `node_modules/${name}/dist/index.js`, suggest: `./node_modules/${name}/dist/**/*.{js,mjs}` });
1772
+ if (declaredRange(baseDir, pkg, name) !== void 0) {
1773
+ targets.push({ label: name, ...packageContentTarget(baseDir, name) });
1584
1774
  }
1585
1775
  }
1586
1776
  if (targets.length === 0) return null;
1587
1777
  const read = readTailwindContent(readFileSync4(join2(baseDir, configFile), "utf8"));
1588
- const patterns = (read?.globs ?? []).filter((g) => !g.trim().startsWith("!")).map(contentGlobToRegExp);
1778
+ const globs = (read?.globs ?? []).filter((g) => !g.trim().startsWith("!"));
1589
1779
  return {
1590
1780
  configFile,
1591
1781
  unreadable: read === void 0,
1592
1782
  dynamic: read?.dynamic ?? false,
1593
- targets: targets.map((t) => ({ ...t, covered: patterns.some((re) => re.test(t.sample)) }))
1783
+ targets: targets.map((t) => ({ ...t, covered: globs.some((g) => contentGlobCovers(g, t.sample, baseDir)) }))
1594
1784
  };
1595
1785
  }
1596
1786
  function checkTailwindContent(baseDir) {
@@ -1605,17 +1795,18 @@ function checkTailwindContent(baseDir) {
1605
1795
  };
1606
1796
  }
1607
1797
  const list = missing.map((t) => `${t.label} \u2192 "${t.suggest}"`).join(" \xB7 ");
1798
+ const note = missing.some((t) => t.suggest.startsWith("../")) ? ` (${CONTENT_PARENT_PATH_NOTE})` : "";
1608
1799
  if (r.unreadable || r.dynamic) {
1609
1800
  return {
1610
1801
  name: "tailwind.content",
1611
1802
  severity: "warn",
1612
- message: `${r.configFile}\uC758 content \uB97C \uC815\uC801\uC73C\uB85C \uB2E4 \uC77D\uC9C0 \uBABB\uD574 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${list}`
1803
+ message: `${r.configFile}\uC758 content \uB97C \uC815\uC801\uC73C\uB85C \uB2E4 \uC77D\uC9C0 \uBABB\uD574 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${list}${note}`
1613
1804
  };
1614
1805
  }
1615
1806
  return {
1616
1807
  name: "tailwind.content",
1617
1808
  severity: "fail",
1618
- message: `${r.configFile}\uC758 content \uAC00 \uCEF4\uD3EC\uB10C\uD2B8 \uACBD\uB85C\uB97C \uB36E\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uD074\uB798\uC2A4\uAC00 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC74C): ${list}`
1809
+ message: `${r.configFile}\uC758 content \uAC00 \uCEF4\uD3EC\uB10C\uD2B8 \uACBD\uB85C\uB97C \uB36E\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uD074\uB798\uC2A4\uAC00 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC74C): ${list}${note}`
1619
1810
  };
1620
1811
  }
1621
1812
  var ANIMATION_PLUGIN_TAILWIND3 = "tailwindcss-animate";
@@ -1656,10 +1847,10 @@ function componentsUseAnimation(baseDir, componentsDir) {
1656
1847
  return false;
1657
1848
  }
1658
1849
  function checkAnimationPlugin(baseDirInput) {
1659
- const baseDir = resolve(baseDirInput);
1850
+ const baseDir = resolveBaseDir(baseDirInput);
1660
1851
  const pkg = readPackageJson(baseDir);
1661
1852
  const config = readAxisConfigLike(baseDir);
1662
- const declared = pkg !== void 0 && hasDependency2(pkg, "@axis-ds/ui-react") !== void 0;
1853
+ const declared = declaredRange(baseDir, pkg, "@axis-ds/ui-react") !== void 0;
1663
1854
  const copied = typeof config?.componentsDir === "string" && componentsUseAnimation(baseDir, config.componentsDir);
1664
1855
  if (!declared && !copied) return null;
1665
1856
  const by = declared ? "@axis-ds/ui-react \uC120\uC5B8" : "componentsDir \uC758 animate-in \uB958 \uD074\uB798\uC2A4";
@@ -1677,7 +1868,7 @@ function checkAnimationPlugin(baseDirInput) {
1677
1868
  const configFile = TAILWIND_CONFIG_FILES.find((f) => existsSync3(join2(baseDir, f)));
1678
1869
  const source = configFile !== void 0 ? stripJsComments(readFileSync4(join2(baseDir, configFile), "utf8")) : "";
1679
1870
  const plugins = configFile !== void 0 ? readAnimationPluginUse(source) : "absent";
1680
- const pluginDeclared = pkg !== void 0 && hasDependency2(pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0;
1871
+ const pluginDeclared = declaredRange(baseDir, pkg, ANIMATION_PLUGIN_TAILWIND3) !== void 0;
1681
1872
  const pluginInstalled = pluginDeclared && (isPnpProject(baseDir) || findInstalledPackage(baseDir, ANIMATION_PLUGIN_TAILWIND3) !== void 0);
1682
1873
  if (plugins === "found" && pluginDeclared && pluginInstalled) {
1683
1874
  return { name: "animation", severity: "pass", message: `${configFile}\uC758 plugins \uC5D0 ${ANIMATION_PLUGIN_TAILWIND3} \uAC00 \uC788\uC2B5\uB2C8\uB2E4` };
@@ -1769,7 +1960,7 @@ function selectUtilsDependencies(tailwind) {
1769
1960
  }
1770
1961
 
1771
1962
  // ../axis-registry-core/src/add/safe-write.ts
1772
- import { constants as fsConstants, existsSync as existsSync4, lstatSync as lstatSync2, realpathSync, statSync as statSync2 } from "fs";
1963
+ import { constants as fsConstants, existsSync as existsSync4, lstatSync as lstatSync2, realpathSync as realpathSync3, statSync as statSync2 } from "fs";
1773
1964
  import path4 from "path";
1774
1965
  import fs2 from "fs-extra";
1775
1966
  var NEW_FILE_FLAGS = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | (fsConstants.O_NOFOLLOW ?? 0);
@@ -1796,12 +1987,12 @@ function nearestExisting(p) {
1796
1987
  return cur;
1797
1988
  }
1798
1989
  function escapeReason(root, target, options = {}) {
1799
- const realRoot = realpathSync(root);
1990
+ const realRoot = realpathSync3(root);
1800
1991
  if (!isSameOrInside(path4.resolve(root), path4.resolve(target)) || path4.resolve(target) === path4.resolve(root)) {
1801
1992
  return `\uACBD\uB85C\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4(${target})`;
1802
1993
  }
1803
1994
  const anchor = nearestExisting(path4.dirname(target));
1804
- const realAnchor = realpathSync(anchor);
1995
+ const realAnchor = realpathSync3(anchor);
1805
1996
  if (!isSameOrInside(realRoot, realAnchor)) {
1806
1997
  return `\uC0C1\uC704 \uB514\uB809\uD130\uB9AC\uC758 \uC2E4\uC81C \uC704\uCE58(${realAnchor})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`;
1807
1998
  }
@@ -1816,7 +2007,7 @@ function escapeReason(root, target, options = {}) {
1816
2007
  const shown = path4.relative(path4.resolve(root), path4.resolve(target)).split(path4.sep).join("/");
1817
2008
  let realTarget;
1818
2009
  try {
1819
- realTarget = realpathSync(target);
2010
+ realTarget = realpathSync3(target);
1820
2011
  } catch {
1821
2012
  return `\uAE30\uC874 \uD30C\uC77C ${shown} \uC774 \uAE68\uC9C4 \uC2EC\uBCFC\uB9AD \uB9C1\uD06C\uB77C \uB530\uB77C\uAC08 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(\uB9C1\uD06C\uB97C \uC9C0\uC6B0\uAC70\uB098 \uACE0\uCE5C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694)`;
1822
2013
  }
@@ -1849,8 +2040,8 @@ function isSymlink(p) {
1849
2040
  function outsideLinkTarget(root, target) {
1850
2041
  if (!isSymlink(target)) return null;
1851
2042
  try {
1852
- const realTarget = realpathSync(target);
1853
- return isSameOrInside(realpathSync(root), realTarget) ? null : realTarget;
2043
+ const realTarget = realpathSync3(target);
2044
+ return isSameOrInside(realpathSync3(root), realTarget) ? null : realTarget;
1854
2045
  } catch {
1855
2046
  return null;
1856
2047
  }
@@ -1867,10 +2058,10 @@ function hardLinkMessage(shownPath, nlink) {
1867
2058
  return `\uAE30\uC874 \uD30C\uC77C ${shownPath} \uC774 \uB2E4\uB978 \uACBD\uB85C\uC640 \uD558\uB4DC\uB9C1\uD06C\uB85C \uC774\uC5B4\uC9C4 \uD30C\uC77C\uC774\uB77C(\uB9C1\uD06C \uC218 ${nlink}) \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB36E\uC5B4\uC4F0\uBA74 \uC774\uC5B4\uC9C4 \uB2E4\uB978 \uACBD\uB85C\uC758 \uB0B4\uC6A9\uB3C4 \uBC14\uB01D\uB2C8\uB2E4. \uD558\uB4DC\uB9C1\uD06C\uB97C \uB04A\uC740(\uD30C\uC77C\uC744 \uBCF5\uC0AC\uD574 \uBC14\uAFBC) \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694`;
1868
2059
  }
1869
2060
  function writtenOutside(root, target) {
1870
- const realRoot = realpathSync(root);
2061
+ const realRoot = realpathSync3(root);
1871
2062
  let realTarget;
1872
2063
  try {
1873
- realTarget = realpathSync(target);
2064
+ realTarget = realpathSync3(target);
1874
2065
  } catch {
1875
2066
  return target;
1876
2067
  }
@@ -1904,8 +2095,8 @@ async function writeNoFollow(target, content, mode) {
1904
2095
  return actual;
1905
2096
  }
1906
2097
  function checkParentInside(root, target) {
1907
- const realRoot = realpathSync(root);
1908
- const realParent = realpathSync(path4.dirname(target));
2098
+ const realRoot = realpathSync3(root);
2099
+ const realParent = realpathSync3(path4.dirname(target));
1909
2100
  if (!isSameOrInside(realRoot, realParent)) {
1910
2101
  return `\uBD80\uBAA8 \uB514\uB809\uD130\uB9AC\uC758 \uC2E4\uC81C \uC704\uCE58(${realParent})\uAC00 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC \uBC16\uC785\uB2C8\uB2E4`;
1911
2102
  }
@@ -2179,11 +2370,12 @@ function missingDependencies(root, items) {
2179
2370
  pkg = void 0;
2180
2371
  }
2181
2372
  const ranges = selectUtilsDependencies(detectTailwind(root, pkg));
2373
+ const rootPkg = pkg !== void 0 ? workspaceRootPackage(root) ?? null : null;
2182
2374
  const specs = {};
2183
2375
  for (const item of items) {
2184
2376
  for (const dep of item.dependencies) {
2185
2377
  const name = dependencyName(dep);
2186
- if (pkg !== void 0 && hasDependency(pkg, name) !== void 0) continue;
2378
+ if (declaredDependency(root, pkg, name, rootPkg) !== void 0) continue;
2187
2379
  if (name in specs) continue;
2188
2380
  const explicit = dep.length > name.length ? dep.slice(name.length + 1) : void 0;
2189
2381
  specs[name] = explicit ?? ranges[name];
@@ -2199,9 +2391,7 @@ function dependencyName(spec) {
2199
2391
  }
2200
2392
  function addCommandForSpecs(installCommand, specs) {
2201
2393
  const args = Object.entries(specs).map(([name, range]) => range ? `"${name}@${range}"` : name).join(" ");
2202
- if (installCommand.startsWith("yarn")) return `yarn add ${args}`;
2203
- if (installCommand.startsWith("npm")) return `npm install ${args}`;
2204
- return `pnpm add ${args}`;
2394
+ return `${addCommandPrefix(installCommand)} ${args}`;
2205
2395
  }
2206
2396
  function rel(root, p) {
2207
2397
  return toPosix(path5.relative(root, p));
@@ -4427,7 +4617,7 @@ import path9 from "path";
4427
4617
  // src/tools/brand-core.ts
4428
4618
  import { existsSync as existsSync8, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
4429
4619
  import { createRequire } from "module";
4430
- import { dirname as dirname3, join as join4, relative, resolve as resolve3, sep } from "path";
4620
+ import { dirname as dirname4, join as join4, relative as relative2, resolve as resolve3, sep as sep2 } from "path";
4431
4621
  var TOKENS_PACKAGE = "@axis-ds/tokens";
4432
4622
  var MIN_BRAND_TOKENS_VERSION = "1.3.0";
4433
4623
  var TOKENS_DEPENDENCY_MIN_VERSION = "1.6.0";
@@ -4457,7 +4647,7 @@ function findTokensPackageJson(baseDir) {
4457
4647
  for (; ; ) {
4458
4648
  const candidate = join4(dir, "node_modules", TOKENS_PACKAGE, "package.json");
4459
4649
  if (existsSync8(candidate)) return candidate;
4460
- const parent = dirname3(dir);
4650
+ const parent = dirname4(dir);
4461
4651
  if (parent === dir) return void 0;
4462
4652
  dir = parent;
4463
4653
  }
@@ -4541,7 +4731,7 @@ function inspectBrandImport(baseDir) {
4541
4731
  if (!location.path) {
4542
4732
  return { ...base, state: "css-missing", imports: [] };
4543
4733
  }
4544
- const cssFile = relative(root, location.path).split(sep).join("/");
4734
+ const cssFile = relative2(root, location.path).split(sep2).join("/");
4545
4735
  const imports = [...new Set(findBrandImports(readFileSync8(location.path, "utf8")))];
4546
4736
  let state;
4547
4737
  if (imports.includes(brand)) state = "match";
@@ -4657,7 +4847,7 @@ function findBrandActivation(baseDir) {
4657
4847
  const providerTexts = [];
4658
4848
  for (const m of text.matchAll(/from\s+["']\.\/(providers?)["']/g)) {
4659
4849
  for (const ext of [".tsx", ".jsx", ".ts", ".js"]) {
4660
- const rel2 = `${dirname3(candidate)}/${m[1]}${ext}`;
4850
+ const rel2 = `${dirname4(candidate)}/${m[1]}${ext}`;
4661
4851
  const p = join4(root, rel2);
4662
4852
  if (isFile2(p)) providerTexts.push({ rel: rel2, text: stripJsLikeComments(readFileSync8(p, "utf8")) });
4663
4853
  }
@@ -4728,7 +4918,7 @@ function getBrand(baseDir, name) {
4728
4918
 
4729
4919
  // ../axis-registry-core/src/template/dependencies-core.ts
4730
4920
  import { readFileSync as readFileSync9 } from "fs";
4731
- import { join as join5, resolve as resolve4 } from "path";
4921
+ import { join as join5 } from "path";
4732
4922
  var REQUIRED_DEPENDENCIES = ["tailwindcss"];
4733
4923
  var RECOMMENDED_DEPENDENCIES = ["clsx", "tailwind-merge"];
4734
4924
  function declaredAxisPackages(pkg) {
@@ -4741,7 +4931,7 @@ function declaredAxisPackages(pkg) {
4741
4931
  return out;
4742
4932
  }
4743
4933
  function checkDependencies(baseDirInput) {
4744
- const baseDir = resolve4(baseDirInput);
4934
+ const baseDir = resolveBaseDir(baseDirInput);
4745
4935
  let pkg;
4746
4936
  try {
4747
4937
  const parsed = JSON.parse(readFileSync9(join5(baseDir, "package.json"), "utf8"));
@@ -4753,13 +4943,18 @@ function checkDependencies(baseDirInput) {
4753
4943
  }
4754
4944
  return { name: "dependencies", severity: "fail", message: "package.json \uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4(JSON \uD655\uC778)" };
4755
4945
  }
4756
- const missingRequired = REQUIRED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d));
4946
+ const rootPkg = workspaceRootPackage(baseDir) ?? null;
4947
+ const declared = (d) => declaredDependency(baseDir, pkg, d, rootPkg);
4948
+ const fromRoot = (d) => declared(d)?.source === "root";
4949
+ const missingRequired = REQUIRED_DEPENDENCIES.filter((d) => declared(d) === void 0);
4757
4950
  if (missingRequired.length > 0) {
4758
4951
  return { name: "dependencies", severity: "fail", message: `\uD544\uC218 \uC758\uC874\uC131 \uB204\uB77D: ${missingRequired.join(", ")}` };
4759
4952
  }
4760
- const missingRecommended = RECOMMENDED_DEPENDENCIES.filter((d) => !hasDependency(pkg, d));
4953
+ const missingRecommended = RECOMMENDED_DEPENDENCIES.filter((d) => declared(d) === void 0);
4954
+ const rootDeclared = [...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => fromRoot(d));
4955
+ const rootNote = rootDeclared.length > 0 ? `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uB8E8\uD2B8\uC5D0 \uC120\uC5B8: ${rootDeclared.join(", ")}` : void 0;
4761
4956
  const targets = [
4762
- ...[...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => hasDependency(pkg, d) !== void 0),
4957
+ ...[...REQUIRED_DEPENDENCIES, ...RECOMMENDED_DEPENDENCIES].filter((d) => declared(d) !== void 0),
4763
4958
  ...declaredAxisPackages(pkg)
4764
4959
  ];
4765
4960
  const pnp = isPnpProject(baseDir);
@@ -4769,11 +4964,14 @@ function checkDependencies(baseDirInput) {
4769
4964
  if (notInstalled.length > 0) {
4770
4965
  problems.push(`\uC120\uC5B8\uB410\uC9C0\uB9CC \uC124\uCE58\uB418\uC9C0 \uC54A\uC740 \uC758\uC874\uC131: ${notInstalled.join(", ")} \u2192 ${detectInstallCommand(baseDir)}`);
4771
4966
  }
4772
- if (problems.length > 0) return { name: "dependencies", severity: "warn", message: problems.join(" / ") };
4967
+ if (problems.length > 0) {
4968
+ return { name: "dependencies", severity: "warn", message: problems.join(" / ") + (rootNote ? ` (${rootNote})` : "") };
4969
+ }
4970
+ const note = rootNote ? `, ${rootNote}` : "";
4773
4971
  return {
4774
4972
  name: "dependencies",
4775
4973
  severity: "pass",
4776
- message: pnp ? `\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uC120\uC5B8\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (Plug'n'Play \uB77C \uC124\uCE58\uBCF8\uC740 \uD655\uC778\uD558\uC9C0 \uC54A\uC74C, ${targets.length}\uAC1C)` : `\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uC120\uC5B8 \xB7 \uC124\uCE58\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (${targets.length}\uAC1C \uD655\uC778)`
4974
+ message: pnp ? `\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uC120\uC5B8\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (Plug'n'Play \uB77C \uC124\uCE58\uBCF8\uC740 \uD655\uC778\uD558\uC9C0 \uC54A\uC74C, ${targets.length}\uAC1C${note})` : `\uD544\uC218 \uBC0F \uAD8C\uC7A5 \uC758\uC874\uC131\uC774 \uC120\uC5B8 \xB7 \uC124\uCE58\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (${targets.length}\uAC1C \uD655\uC778${note})`
4777
4975
  };
4778
4976
  }
4779
4977
 
@@ -4831,6 +5029,7 @@ async function handleGetTemplate(params) {
4831
5029
  async function handleApplyTemplate(params) {
4832
5030
  const detail = await fetchTemplateDetail(params.name);
4833
5031
  const baseDir = path9.resolve(params.targetDir);
5032
+ const installCommand = detectInstallCommand(baseDir);
4834
5033
  const files = [];
4835
5034
  for (const file of detail.files) {
4836
5035
  const dest = path9.join(baseDir, file.path);
@@ -4868,7 +5067,8 @@ async function handleApplyTemplate(params) {
4868
5067
  files,
4869
5068
  dependencies: detail.dependencies || {},
4870
5069
  devDependencies: detail.devDependencies || {},
4871
- dryRun: !!params.dryRun
5070
+ dryRun: !!params.dryRun,
5071
+ installCommand
4872
5072
  };
4873
5073
  }
4874
5074
  async function handleDiffTemplate(params) {
@@ -5075,11 +5275,12 @@ function formatApplyTemplateResult(result) {
5075
5275
  const devDeps = Object.entries(result.devDependencies);
5076
5276
  if (deps.length > 0 || devDeps.length > 0) {
5077
5277
  lines.push("", "### \uD544\uC694\uD55C \uC758\uC874\uC131", "");
5278
+ const installCommand = result.installCommand ?? "pnpm install";
5078
5279
  if (deps.length > 0) {
5079
- lines.push(`\`pnpm add ${deps.map(([k, v]) => `${k}@${v}`).join(" ")}\``);
5280
+ lines.push(`\`${addCommandFor(installCommand, result.dependencies)}\``);
5080
5281
  }
5081
5282
  if (devDeps.length > 0) {
5082
- lines.push(`\`pnpm add -D ${devDeps.map(([k, v]) => `${k}@${v}`).join(" ")}\``);
5283
+ lines.push(`\`${addCommandFor(installCommand, result.devDependencies, { dev: true })}\``);
5083
5284
  }
5084
5285
  }
5085
5286
  return lines.join("\n");
@@ -5124,6 +5325,11 @@ var TOKENS_INSTALL_COMMAND = addCommandFor("pnpm install", { [TOKENS_PACKAGE]: `
5124
5325
  function baseDirOf(targetDir) {
5125
5326
  return path10.resolve(targetDir || process.cwd());
5126
5327
  }
5328
+ function tokensInstallCommandFor(targetDir) {
5329
+ return addCommandFor(detectInstallCommand(baseDirOf(targetDir)), {
5330
+ [TOKENS_PACKAGE]: `^${TOKENS_DEPENDENCY_MIN_VERSION}`
5331
+ });
5332
+ }
5127
5333
  async function handleListBrands(params) {
5128
5334
  return listBrands(baseDirOf(params.targetDir));
5129
5335
  }
@@ -5134,32 +5340,32 @@ async function handleGetBrand(params) {
5134
5340
  }
5135
5341
  return getBrand(baseDirOf(params.targetDir), name);
5136
5342
  }
5137
- function formatTokensStatusGuide(status, version) {
5343
+ function formatTokensStatusGuide(status, version, installCommand = TOKENS_INSTALL_COMMAND) {
5138
5344
  switch (status) {
5139
5345
  case "not-installed":
5140
5346
  return [
5141
5347
  `${TOKENS_PACKAGE} \uAC00 \uC124\uCE58\uB3FC \uC788\uC9C0 \uC54A\uC544 \uBE0C\uB79C\uB4DC\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`,
5142
5348
  "",
5143
- `- \uC124\uCE58: \`${TOKENS_INSTALL_COMMAND}\``
5349
+ `- \uC124\uCE58: \`${installCommand}\``
5144
5350
  ].join("\n");
5145
5351
  case "unsupported":
5146
5352
  return [
5147
5353
  `${TOKENS_PACKAGE} ${version ?? "(\uBC84\uC804 \uBAA8\uB984)"} \uC740 \uBE0C\uB79C\uB4DC\uB97C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(${MIN_BRAND_TOKENS_VERSION} \uC774\uC0C1 \uD544\uC694).`,
5148
5354
  "",
5149
- `- \uC5C5\uADF8\uB808\uC774\uB4DC: \`${TOKENS_INSTALL_COMMAND}\``
5355
+ `- \uC5C5\uADF8\uB808\uC774\uB4DC: \`${installCommand}\``
5150
5356
  ].join("\n");
5151
5357
  case "not-built":
5152
5358
  return [
5153
5359
  `${TOKENS_PACKAGE}${version ? ` ${version}` : ""} \uB294 \uC788\uC9C0\uB9CC \uBE4C\uB4DC \uC0B0\uCD9C\uBB3C\uC774 \uC5C6\uC5B4 \uBE0C\uB79C\uB4DC\uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`,
5154
5360
  "",
5155
- `- \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uBA74 \`pnpm --filter ${TOKENS_PACKAGE} build\`, \uC544\uB2C8\uBA74 \uC7AC\uC124\uCE58: \`${TOKENS_INSTALL_COMMAND}\``
5361
+ `- \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uBA74 \`${workspaceRunCommand(installCommand, TOKENS_PACKAGE, "build")}\`, \uC544\uB2C8\uBA74 \uC7AC\uC124\uCE58: \`${installCommand}\``
5156
5362
  ].join("\n");
5157
5363
  }
5158
5364
  }
5159
- function formatListBrandsResult(result) {
5365
+ function formatListBrandsResult(result, installCommand) {
5160
5366
  const lines = ["## AXIS \uBE0C\uB79C\uB4DC\n"];
5161
5367
  if (result.status !== "ok") {
5162
- lines.push(formatTokensStatusGuide(result.status, result.version));
5368
+ lines.push(formatTokensStatusGuide(result.status, result.version, installCommand));
5163
5369
  return lines.join("\n");
5164
5370
  }
5165
5371
  if (result.brands.length === 0) {
@@ -5193,10 +5399,10 @@ function tokenTable(brand) {
5193
5399
  }
5194
5400
  return lines;
5195
5401
  }
5196
- function formatGetBrandResult(result, name) {
5402
+ function formatGetBrandResult(result, name, installCommand) {
5197
5403
  if (result.status !== "ok") {
5198
5404
  return [`## \uBE0C\uB79C\uB4DC: ${name}
5199
- `, formatTokensStatusGuide(result.status, result.version)].join("\n");
5405
+ `, formatTokensStatusGuide(result.status, result.version, installCommand)].join("\n");
5200
5406
  }
5201
5407
  const brand = result.brand;
5202
5408
  if (!brand) {
@@ -5810,7 +6016,7 @@ server.tool(
5810
6016
  async ({ targetDir }) => {
5811
6017
  try {
5812
6018
  const result = await handleListBrands({ targetDir });
5813
- const formatted = formatListBrandsResult(result);
6019
+ const formatted = formatListBrandsResult(result, tokensInstallCommandFor(targetDir));
5814
6020
  return {
5815
6021
  content: [
5816
6022
  {
@@ -5835,7 +6041,7 @@ server.tool(
5835
6041
  );
5836
6042
  server.tool(
5837
6043
  "axis.get_brand",
5838
- "\uBE0C\uB79C\uB4DC \uD558\uB098\uC758 import \uACBD\uB85C \xB7 Provider \uC124\uC815 \uC608\uC2DC(defaultBrand) \xB7 \uC8FC\uC694 \uD1A0\uD070 \xB7 \uBCF4\uC815 \uB0B4\uC5ED\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.",
6044
+ "\uBE0C\uB79C\uB4DC \uD558\uB098\uC758 import \uACBD\uB85C \xB7 \uBE0C\uB79C\uB4DC \uCF1C\uAE30 \uC608\uC2DC(<html data-brand> \xB7 ThemeProvider setBrand) \xB7 \uC8FC\uC694 \uD1A0\uD070 \xB7 \uBCF4\uC815 \uB0B4\uC5ED\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.",
5839
6045
  {
5840
6046
  name: z.string().describe("\uBE0C\uB79C\uB4DC \uC774\uB984 (\uC608: ontology)"),
5841
6047
  targetDir: z.string().optional().describe("\uB300\uC0C1 \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD1A0\uB9AC (\uAE30\uBCF8: \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC)")
@@ -5843,7 +6049,7 @@ server.tool(
5843
6049
  async ({ name, targetDir }) => {
5844
6050
  try {
5845
6051
  const result = await handleGetBrand({ name, targetDir });
5846
- const formatted = formatGetBrandResult(result, name);
6052
+ const formatted = formatGetBrandResult(result, name, tokensInstallCommandFor(targetDir));
5847
6053
  return {
5848
6054
  content: [
5849
6055
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axis-ds/mcp",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "type": "module",
5
5
  "description": "AXIS Design System - MCP Server for AI-assisted component discovery",
6
6
  "bin": {