@alcyone-labs/arg-parser 2.5.0 → 2.6.0

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.
package/dist/index.cjs CHANGED
@@ -1075,6 +1075,29 @@ class ConfigurationManager {
1075
1075
  }
1076
1076
  }
1077
1077
  }
1078
+ const zodDxtOptionsSchema = zod.z.object({
1079
+ sensitive: zod.z.boolean().optional().describe("Whether this field should be marked as sensitive in DXT user_config"),
1080
+ localDefault: zod.z.string().optional().describe("Default value specific to DXT sandbox environment"),
1081
+ type: zod.z.enum(["string", "directory", "file", "boolean", "number"]).optional().describe("DXT input type - determines UI component in DXT clients"),
1082
+ multiple: zod.z.boolean().optional().describe("Allow multiple values (for arrays)"),
1083
+ min: zod.z.number().optional().describe("Minimum value (for number type)"),
1084
+ max: zod.z.number().optional().describe("Maximum value (for number type)"),
1085
+ default: zod.z.any().optional().describe("DXT-specific default value (overrides localDefault if provided)"),
1086
+ title: zod.z.string().optional().describe("Custom title for the user_config field")
1087
+ }).strict().refine(
1088
+ (data2) => {
1089
+ if ((data2.min !== void 0 || data2.max !== void 0) && data2.type !== "number") {
1090
+ return false;
1091
+ }
1092
+ if (data2.min !== void 0 && data2.max !== void 0 && data2.min > data2.max) {
1093
+ return false;
1094
+ }
1095
+ return true;
1096
+ },
1097
+ {
1098
+ message: "Invalid dxtOptions: min/max can only be used with type 'number', and min must be <= max"
1099
+ }
1100
+ );
1078
1101
  const zodFlagSchema = zod.z.object({
1079
1102
  name: zod.z.string().min(1, "Flag name cannot be empty").describe(
1080
1103
  "The output property name, used as a return key `{name: value}`. Must be unique."
@@ -1146,7 +1169,8 @@ const zodFlagSchema = zod.z.object({
1146
1169
  enum: zod.z.array(zod.z.any()).optional().describe("Array of allowed values for the flag."),
1147
1170
  env: zod.z.union([zod.z.string(), zod.z.array(zod.z.string())]).optional().describe(
1148
1171
  "Environment variables that should be set from this flag's value in DXT packages."
1149
- )
1172
+ ),
1173
+ dxtOptions: zodDxtOptionsSchema.optional().describe("DXT-specific configuration options for enhanced DXT manifest generation")
1150
1174
  }).transform((obj) => {
1151
1175
  const newObj = { ...obj };
1152
1176
  if ("default" in newObj && newObj["default"] !== void 0 && !("defaultValue" in newObj)) {
@@ -1344,6 +1368,353 @@ echo "Mock DXT build script for ${serverInfo.name}"`;
1344
1368
  return process.env["NODE_ENV"] === "test" || ((_a = process.argv[0]) == null ? void 0 : _a.includes("vitest")) || ((_b = process.argv[1]) == null ? void 0 : _b.includes("vitest")) || ((_c = process.argv[1]) == null ? void 0 : _c.includes("tinypool"));
1345
1369
  }
1346
1370
  }
1371
+ function detectEntryPoint() {
1372
+ try {
1373
+ if (process.argv[1] && fs__namespace.existsSync(process.argv[1])) {
1374
+ return process.argv[1];
1375
+ }
1376
+ if (typeof require !== "undefined" && require.main && require.main.filename) {
1377
+ return require.main.filename;
1378
+ }
1379
+ return null;
1380
+ } catch {
1381
+ return null;
1382
+ }
1383
+ }
1384
+ function getEntryPointFromImportMeta(importMetaUrl) {
1385
+ if (importMetaUrl.startsWith("file://")) {
1386
+ return decodeURIComponent(importMetaUrl.replace("file://", ""));
1387
+ }
1388
+ return importMetaUrl;
1389
+ }
1390
+ function normalizePath(path2) {
1391
+ return path2.trim();
1392
+ }
1393
+ function resolveLogPath(logPath, fallbackEntryPoint) {
1394
+ if (typeof logPath === "string") {
1395
+ const pathWithVariables2 = DxtPathResolver.substituteVariables(
1396
+ logPath,
1397
+ DxtPathResolver.detectContext()
1398
+ );
1399
+ const normalizedPath2 = normalizePath(pathWithVariables2);
1400
+ if (path__namespace.isAbsolute(normalizedPath2)) {
1401
+ return normalizedPath2;
1402
+ }
1403
+ if (normalizedPath2.startsWith("cwd:")) {
1404
+ const relativePath = normalizedPath2.slice(4);
1405
+ return path__namespace.resolve(process.cwd(), relativePath);
1406
+ }
1407
+ const entryPoint = detectEntryPoint() || fallbackEntryPoint;
1408
+ if (entryPoint) {
1409
+ return path__namespace.resolve(path__namespace.dirname(entryPoint), normalizedPath2);
1410
+ }
1411
+ console.warn(
1412
+ `Warning: Could not detect entry point for log path resolution. Using process.cwd() as fallback. Path: ${normalizedPath2}`
1413
+ );
1414
+ return path__namespace.resolve(process.cwd(), normalizedPath2);
1415
+ }
1416
+ const { path: logFilePath, relativeTo = "entry", basePath } = logPath;
1417
+ const pathWithVariables = DxtPathResolver.substituteVariables(
1418
+ logFilePath,
1419
+ DxtPathResolver.detectContext()
1420
+ );
1421
+ const normalizedPath = normalizePath(pathWithVariables);
1422
+ switch (relativeTo) {
1423
+ case "absolute":
1424
+ if (basePath) {
1425
+ const resolvedBasePath = DxtPathResolver.substituteVariables(
1426
+ basePath,
1427
+ DxtPathResolver.detectContext()
1428
+ );
1429
+ return path__namespace.resolve(resolvedBasePath, normalizedPath);
1430
+ }
1431
+ if (path__namespace.isAbsolute(normalizedPath)) {
1432
+ return normalizedPath;
1433
+ }
1434
+ console.warn(
1435
+ `Warning: relativeTo 'absolute' specified but no basePath provided and path is not absolute. Using process.cwd() as fallback. Path: ${normalizedPath}`
1436
+ );
1437
+ return path__namespace.resolve(process.cwd(), normalizedPath);
1438
+ case "cwd":
1439
+ return path__namespace.resolve(process.cwd(), normalizedPath);
1440
+ case "entry":
1441
+ default:
1442
+ const entryPoint = detectEntryPoint() || fallbackEntryPoint;
1443
+ if (entryPoint) {
1444
+ return path__namespace.resolve(path__namespace.dirname(entryPoint), normalizedPath);
1445
+ }
1446
+ console.warn(
1447
+ `Warning: Could not detect entry point for log path resolution. Using process.cwd() as fallback. Path: ${normalizedPath}`
1448
+ );
1449
+ return path__namespace.resolve(process.cwd(), normalizedPath);
1450
+ }
1451
+ }
1452
+ function entryRelative(path2) {
1453
+ return {
1454
+ path: path2,
1455
+ relativeTo: "entry"
1456
+ };
1457
+ }
1458
+ function cwdRelative(path2) {
1459
+ return {
1460
+ path: path2,
1461
+ relativeTo: "cwd"
1462
+ };
1463
+ }
1464
+ function absolutePath(path2, basePath) {
1465
+ return {
1466
+ path: path2,
1467
+ relativeTo: "absolute",
1468
+ basePath
1469
+ };
1470
+ }
1471
+ function legacyCwdPath(path2) {
1472
+ return `cwd:${path2}`;
1473
+ }
1474
+ const _DxtPathResolver = class _DxtPathResolver {
1475
+ /**
1476
+ * Detects the current execution context
1477
+ * @param forceRefresh - Force refresh of cached context
1478
+ * @returns Path context information
1479
+ */
1480
+ static detectContext(forceRefresh = false) {
1481
+ if (!forceRefresh && this._cachedContext) {
1482
+ return this._cachedContext;
1483
+ }
1484
+ const context = {
1485
+ isDxt: this.isDxtEnvironment(),
1486
+ userHome: void 0,
1487
+ cwd: typeof process !== "undefined" && typeof process.cwd === "function" ? process.cwd() : void 0
1488
+ };
1489
+ const entryPoint = detectEntryPoint();
1490
+ if (entryPoint) {
1491
+ context.entryDir = path__namespace.dirname(entryPoint);
1492
+ }
1493
+ if (context.isDxt) {
1494
+ context.extensionDir = this.detectDxtExtensionDir();
1495
+ }
1496
+ this._cachedContext = context;
1497
+ return context;
1498
+ }
1499
+ /**
1500
+ * Checks if the current environment is a DXT environment
1501
+ * @returns True if running in DXT, false otherwise
1502
+ */
1503
+ static isDxtEnvironment() {
1504
+ if (process.env["DXT_EXTENSION_DIR"] || process.env["CLAUDE_DESKTOP_DXT"]) {
1505
+ return true;
1506
+ }
1507
+ const dxtIndicators = [
1508
+ "manifest.json",
1509
+ // DXT packages have manifest.json
1510
+ ".dxt"
1511
+ // DXT marker file
1512
+ ];
1513
+ for (const indicator of dxtIndicators) {
1514
+ const indicatorPath = path__namespace.join(process.cwd(), indicator);
1515
+ if (fs__namespace.existsSync(indicatorPath)) {
1516
+ if (indicator === "manifest.json") {
1517
+ try {
1518
+ const manifest = JSON.parse(fs__namespace.readFileSync(indicatorPath, "utf-8"));
1519
+ if (manifest.server && manifest.user_config) {
1520
+ return true;
1521
+ }
1522
+ } catch {
1523
+ }
1524
+ } else {
1525
+ return true;
1526
+ }
1527
+ }
1528
+ }
1529
+ const cwd = process.cwd();
1530
+ if (cwd.includes("claude-desktop") || cwd.includes("extensions")) {
1531
+ return true;
1532
+ }
1533
+ return false;
1534
+ }
1535
+ /**
1536
+ * Detects the DXT extension directory
1537
+ * @returns DXT extension directory path or undefined
1538
+ */
1539
+ static detectDxtExtensionDir() {
1540
+ if (process.env["DXT_EXTENSION_DIR"]) {
1541
+ return process.env["DXT_EXTENSION_DIR"];
1542
+ }
1543
+ const cwd = process.cwd();
1544
+ if (fs__namespace.existsSync(path__namespace.join(cwd, "manifest.json"))) {
1545
+ return cwd;
1546
+ }
1547
+ let currentDir = cwd;
1548
+ for (let i = 0; i < 3; i++) {
1549
+ const parentDir = path__namespace.dirname(currentDir);
1550
+ if (parentDir === currentDir) break;
1551
+ if (fs__namespace.existsSync(path__namespace.join(parentDir, "manifest.json"))) {
1552
+ return parentDir;
1553
+ }
1554
+ currentDir = parentDir;
1555
+ }
1556
+ return void 0;
1557
+ }
1558
+ /**
1559
+ * Resolves a path with DXT variable substitution
1560
+ * @param inputPath - Path that may contain DXT variables
1561
+ * @param context - Optional context (will be detected if not provided)
1562
+ * @param config - Optional configuration for variable substitution
1563
+ * @returns Resolved absolute path
1564
+ */
1565
+ static resolvePath(inputPath, context, config) {
1566
+ const ctx = context || this.detectContext();
1567
+ const resolvedPath = this.substituteVariables(inputPath, ctx, config);
1568
+ if (path__namespace.isAbsolute(resolvedPath)) {
1569
+ return resolvedPath;
1570
+ }
1571
+ if (ctx.isDxt && ctx.extensionDir) {
1572
+ return path__namespace.resolve(ctx.extensionDir, resolvedPath);
1573
+ } else if (ctx.entryDir) {
1574
+ return path__namespace.resolve(ctx.entryDir, resolvedPath);
1575
+ } else {
1576
+ return path__namespace.resolve(ctx.cwd || process.cwd(), resolvedPath);
1577
+ }
1578
+ }
1579
+ /**
1580
+ * Substitutes DXT variables in a path string
1581
+ * @param inputPath - Path containing variables like ${HOME}, ${__dirname}, etc.
1582
+ * @param context - Path context
1583
+ * @param config - Variable substitution configuration
1584
+ * @returns Path with variables substituted
1585
+ */
1586
+ static substituteVariables(inputPath, context, config) {
1587
+ const safeHomedir = () => "/tmp";
1588
+ const homeDir = context.userHome || safeHomedir();
1589
+ const variables = {
1590
+ // Standard DXT variables
1591
+ HOME: homeDir,
1592
+ DOCUMENTS: path__namespace.join(homeDir, "Documents"),
1593
+ DOWNLOADS: path__namespace.join(homeDir, "Downloads"),
1594
+ DESKTOP: path__namespace.join(homeDir, "Desktop"),
1595
+ pathSeparator: path__namespace.sep,
1596
+ // Context-specific variables
1597
+ __dirname: context.isDxt && context.extensionDir ? context.extensionDir : context.entryDir || context.cwd || process.cwd(),
1598
+ // DXT-specific variables
1599
+ ...context.isDxt && context.extensionDir && {
1600
+ DXT_DIR: context.extensionDir,
1601
+ EXTENSION_DIR: context.extensionDir
1602
+ },
1603
+ // Custom variables override defaults
1604
+ ...config == null ? void 0 : config.customVariables
1605
+ };
1606
+ return inputPath.replace(/\$\{([^}]*)\}/g, (match, variableName) => {
1607
+ if (!variableName.trim()) {
1608
+ if (config == null ? void 0 : config.allowUndefined) {
1609
+ return match;
1610
+ }
1611
+ throw new Error(
1612
+ `Undefined DXT variable: ${variableName}. Available variables: ${Object.keys(variables).join(", ")}`
1613
+ );
1614
+ }
1615
+ const value = variables[variableName];
1616
+ if (value !== void 0) {
1617
+ return value;
1618
+ }
1619
+ if (config == null ? void 0 : config.allowUndefined) {
1620
+ return match;
1621
+ }
1622
+ throw new Error(
1623
+ `Undefined DXT variable: ${variableName}. Available variables: ${Object.keys(variables).join(", ")}`
1624
+ );
1625
+ });
1626
+ }
1627
+ /**
1628
+ * Creates a path for user data storage
1629
+ * @param filename - Name of the file or subdirectory
1630
+ * @param context - Optional context (will be detected if not provided)
1631
+ * @returns Absolute path for user data
1632
+ */
1633
+ static createUserDataPath(filename, context) {
1634
+ const ctx = context || this.detectContext();
1635
+ if (ctx.isDxt && ctx.extensionDir) {
1636
+ return path__namespace.join(ctx.extensionDir, "data", filename);
1637
+ } else {
1638
+ const safeHomedir = () => "/tmp";
1639
+ const userDataDir = process.env["XDG_DATA_HOME"] || path__namespace.join(ctx.userHome || safeHomedir(), ".local", "share");
1640
+ const appName = this.getAppName(ctx);
1641
+ return path__namespace.join(userDataDir, appName, filename);
1642
+ }
1643
+ }
1644
+ /**
1645
+ * Creates a path for temporary files
1646
+ * @param filename - Name of the temporary file
1647
+ * @param context - Optional context (will be detected if not provided)
1648
+ * @returns Absolute path for temporary file
1649
+ */
1650
+ static createTempPath(filename, context) {
1651
+ const ctx = context || this.detectContext();
1652
+ if (ctx.isDxt && ctx.extensionDir) {
1653
+ return path__namespace.join(ctx.extensionDir, "temp", filename);
1654
+ } else {
1655
+ const safeTmpdir = () => "/tmp";
1656
+ const appName = this.getAppName(ctx);
1657
+ return path__namespace.join(safeTmpdir(), appName, filename);
1658
+ }
1659
+ }
1660
+ /**
1661
+ * Creates a path for configuration files
1662
+ * @param filename - Name of the configuration file
1663
+ * @param context - Optional context (will be detected if not provided)
1664
+ * @returns Absolute path for configuration file
1665
+ */
1666
+ static createConfigPath(filename, context) {
1667
+ const ctx = context || this.detectContext();
1668
+ if (ctx.isDxt && ctx.extensionDir) {
1669
+ return path__namespace.join(ctx.extensionDir, "config", filename);
1670
+ } else {
1671
+ const safeHomedir = () => "/tmp";
1672
+ const configDir = process.env["XDG_CONFIG_HOME"] || path__namespace.join(ctx.userHome || safeHomedir(), ".config");
1673
+ const appName = this.getAppName(ctx);
1674
+ return path__namespace.join(configDir, appName, filename);
1675
+ }
1676
+ }
1677
+ /**
1678
+ * Gets the application name for directory creation
1679
+ * @param context - Path context
1680
+ * @returns Application name or default
1681
+ */
1682
+ static getAppName(context) {
1683
+ try {
1684
+ const packageJsonPath = path__namespace.join(context.entryDir || context.cwd || process.cwd(), "package.json");
1685
+ if (fs__namespace.existsSync(packageJsonPath)) {
1686
+ const packageJson = JSON.parse(fs__namespace.readFileSync(packageJsonPath, "utf-8"));
1687
+ return packageJson.name || "argparser-app";
1688
+ }
1689
+ } catch {
1690
+ }
1691
+ return "argparser-app";
1692
+ }
1693
+ /**
1694
+ * Ensures a directory exists, creating it if necessary
1695
+ * @param dirPath - Directory path to ensure
1696
+ * @returns True if directory exists or was created successfully
1697
+ */
1698
+ static ensureDirectory(dirPath) {
1699
+ try {
1700
+ if (!fs__namespace.existsSync(dirPath)) {
1701
+ fs__namespace.mkdirSync(dirPath, { recursive: true });
1702
+ }
1703
+ return true;
1704
+ } catch (error) {
1705
+ console.warn(`Failed to create directory: ${dirPath}`, error);
1706
+ return false;
1707
+ }
1708
+ }
1709
+ /**
1710
+ * Clears the cached context (useful for testing)
1711
+ */
1712
+ static clearCache() {
1713
+ this._cachedContext = null;
1714
+ }
1715
+ };
1716
+ _DxtPathResolver._cachedContext = null;
1717
+ let DxtPathResolver = _DxtPathResolver;
1347
1718
  class DxtGenerator {
1348
1719
  constructor(argParserInstance) {
1349
1720
  this.argParserInstance = argParserInstance;
@@ -1753,100 +2124,128 @@ class DxtGenerator {
1753
2124
  silent: process.env["NO_SILENCE"] !== "1",
1754
2125
  unbundle: true,
1755
2126
  external: (id, importer) => {
1756
- const external = this.shouldModuleBeExternal(
1757
- id,
1758
- importer,
1759
- withNodeModules
1760
- );
1761
- if (Boolean(process.env["DEBUG"]))
1762
- console.log(
1763
- `[${simpleChalk.blue("External")}] ${simpleChalk.yellow(external ? "true" : "false")} for module: (${simpleChalk.green(id)}), path: '${simpleChalk.grey(importer ?? "")}'`
2127
+ try {
2128
+ const external = this.shouldModuleBeExternal(
2129
+ id,
2130
+ importer,
2131
+ withNodeModules
1764
2132
  );
1765
- return external;
2133
+ if (Boolean(process.env["DEBUG"]))
2134
+ console.log(
2135
+ `[${simpleChalk.blue("External")}] ${simpleChalk.yellow(external ? "true" : "false")} for module: (${simpleChalk.green(id)}), path: '${simpleChalk.grey(importer ?? "")}'`
2136
+ );
2137
+ return Boolean(external);
2138
+ } catch (error) {
2139
+ console.warn(`Warning: Error in external function for ${id}:`, error);
2140
+ return true;
2141
+ }
1766
2142
  },
1767
2143
  noExternal: (id, importer) => {
1768
- const external = this.shouldModuleBeExternal(
1769
- id,
1770
- importer,
1771
- withNodeModules
1772
- );
1773
- if (Boolean(process.env["DEBUG"]))
1774
- console.log(
1775
- `[${simpleChalk.yellow("noExternal")}] ${simpleChalk.yellow(external === false ? "true" : "false")} for module: (${simpleChalk.green(id)}), path: '${simpleChalk.grey(importer ?? "")}'`
2144
+ try {
2145
+ const external = this.shouldModuleBeExternal(
2146
+ id,
2147
+ importer,
2148
+ withNodeModules
1776
2149
  );
1777
- return external === false;
2150
+ if (Boolean(process.env["DEBUG"]))
2151
+ console.log(
2152
+ `[${simpleChalk.yellow("noExternal")}] ${simpleChalk.yellow(external === false ? "true" : "false")} for module: (${simpleChalk.green(id)}), path: '${simpleChalk.grey(importer ?? "")}'`
2153
+ );
2154
+ return Boolean(external === false);
2155
+ } catch (error) {
2156
+ console.warn(`Warning: Error in noExternal function for ${id}:`, error);
2157
+ return false;
2158
+ }
1778
2159
  },
1779
2160
  copy: async (options) => {
1780
2161
  var _a2;
1781
- const outputPaths = [
1782
- "package.json"
1783
- ];
1784
- if (withNodeModules) {
1785
- console.log(
1786
- simpleChalk.gray(
1787
- "📦 Including node_modules in bundle (may take longer)..."
1788
- )
1789
- );
1790
- outputPaths.push("node_modules");
1791
- }
1792
- const dxtPackageRoot = entryDir !== "." && entryDir !== "" ? path__namespace.dirname(options.outDir) : options.outDir;
1793
- if (logoFilename) {
1794
- const currentDir = typeof process !== "undefined" ? process.cwd() : "/test";
1795
- const logoPath = path__namespace.join(currentDir, logoFilename);
1796
- if (fs__namespace.existsSync(logoPath)) {
1797
- console.log(simpleChalk.gray(`Adding logo from: ${logoPath}`));
1798
- outputPaths.push({
1799
- from: logoPath,
1800
- to: path__namespace.join(dxtPackageRoot, logoFilename)
1801
- });
2162
+ try {
2163
+ const outputPaths = [
2164
+ "package.json"
2165
+ ];
2166
+ if (withNodeModules) {
2167
+ console.log(
2168
+ simpleChalk.gray(
2169
+ "📦 Including node_modules in bundle (may take longer)..."
2170
+ )
2171
+ );
2172
+ outputPaths.push("node_modules");
1802
2173
  }
1803
- }
1804
- if ((_a2 = mcpConfig == null ? void 0 : mcpConfig.dxt) == null ? void 0 : _a2.include) {
1805
- console.log(
1806
- simpleChalk.gray(
1807
- "📁 Including additional files from DXT configuration..."
1808
- )
1809
- );
1810
- for (const includeItem of mcpConfig.dxt.include) {
1811
- if (typeof includeItem === "string") {
1812
- const sourcePath = path__namespace.resolve(projectRoot, includeItem);
1813
- if (fs__namespace.existsSync(sourcePath)) {
1814
- console.log(simpleChalk.gray(` • ${includeItem}`));
1815
- outputPaths.push({
1816
- from: sourcePath,
1817
- to: path__namespace.join(dxtPackageRoot, includeItem)
1818
- });
1819
- } else {
1820
- console.warn(
1821
- simpleChalk.yellow(
1822
- ` ⚠ File not found: ${includeItem} (resolved to ${sourcePath})`
1823
- )
1824
- );
1825
- }
1826
- } else {
1827
- const sourcePath = path__namespace.resolve(
1828
- projectRoot,
1829
- includeItem.from
1830
- );
1831
- if (fs__namespace.existsSync(sourcePath)) {
1832
- console.log(
1833
- simpleChalk.gray(` • ${includeItem.from} → ${includeItem.to}`)
2174
+ const dxtPackageRoot = entryDir !== "." && entryDir !== "" ? path__namespace.dirname(options.outDir) : options.outDir;
2175
+ if (logoFilename) {
2176
+ const currentDir = typeof process !== "undefined" ? process.cwd() : "/test";
2177
+ const logoPath = path__namespace.join(currentDir, logoFilename);
2178
+ if (fs__namespace.existsSync(logoPath)) {
2179
+ console.log(simpleChalk.gray(`Adding logo from: ${logoPath}`));
2180
+ outputPaths.push({
2181
+ from: logoPath,
2182
+ to: path__namespace.join(dxtPackageRoot, logoFilename)
2183
+ });
2184
+ }
2185
+ }
2186
+ if ((_a2 = mcpConfig == null ? void 0 : mcpConfig.dxt) == null ? void 0 : _a2.include) {
2187
+ console.log(
2188
+ simpleChalk.gray(
2189
+ "📁 Including additional files from DXT configuration..."
2190
+ )
2191
+ );
2192
+ for (const includeItem of mcpConfig.dxt.include) {
2193
+ if (typeof includeItem === "string") {
2194
+ const resolvedIncludePath = DxtPathResolver.substituteVariables(
2195
+ includeItem,
2196
+ DxtPathResolver.detectContext(),
2197
+ { allowUndefined: true }
2198
+ // Allow undefined variables for flexibility
1834
2199
  );
1835
- outputPaths.push({
1836
- from: sourcePath,
1837
- to: path__namespace.join(dxtPackageRoot, includeItem.to)
1838
- });
2200
+ const sourcePath = path__namespace.resolve(projectRoot, resolvedIncludePath);
2201
+ if (fs__namespace.existsSync(sourcePath)) {
2202
+ console.log(simpleChalk.gray(` • ${resolvedIncludePath}`));
2203
+ outputPaths.push({
2204
+ from: sourcePath,
2205
+ to: path__namespace.join(dxtPackageRoot, resolvedIncludePath)
2206
+ });
2207
+ } else {
2208
+ console.warn(
2209
+ simpleChalk.yellow(
2210
+ ` ⚠ File not found: ${resolvedIncludePath} (resolved to ${sourcePath})`
2211
+ )
2212
+ );
2213
+ }
1839
2214
  } else {
1840
- console.warn(
1841
- simpleChalk.yellow(
1842
- ` ⚠ File not found: ${includeItem.from} (resolved to ${sourcePath})`
1843
- )
2215
+ const resolvedFromPath = DxtPathResolver.substituteVariables(
2216
+ includeItem.from,
2217
+ DxtPathResolver.detectContext(),
2218
+ { allowUndefined: true }
1844
2219
  );
2220
+ const resolvedToPath = DxtPathResolver.substituteVariables(
2221
+ includeItem.to,
2222
+ DxtPathResolver.detectContext(),
2223
+ { allowUndefined: true }
2224
+ );
2225
+ const sourcePath = path__namespace.resolve(projectRoot, resolvedFromPath);
2226
+ if (fs__namespace.existsSync(sourcePath)) {
2227
+ console.log(
2228
+ simpleChalk.gray(` • ${resolvedFromPath} → ${resolvedToPath}`)
2229
+ );
2230
+ outputPaths.push({
2231
+ from: sourcePath,
2232
+ to: path__namespace.join(dxtPackageRoot, resolvedToPath)
2233
+ });
2234
+ } else {
2235
+ console.warn(
2236
+ simpleChalk.yellow(
2237
+ ` ⚠ File not found: ${resolvedFromPath} (resolved to ${sourcePath})`
2238
+ )
2239
+ );
2240
+ }
1845
2241
  }
1846
2242
  }
1847
2243
  }
2244
+ return outputPaths;
2245
+ } catch (error) {
2246
+ console.warn(`Warning: Error in copy function:`, error);
2247
+ return ["package.json"];
1848
2248
  }
1849
- return outputPaths;
1850
2249
  },
1851
2250
  platform: "node",
1852
2251
  plugins: []
@@ -1874,8 +2273,18 @@ export default ${JSON.stringify(buildConfig, null, 2)};
1874
2273
  simpleChalk.gray("📝 Debug config written to dxt/tsdown.config.dxt.ts")
1875
2274
  );
1876
2275
  }
1877
- await build(buildConfig);
1878
- console.log(simpleChalk.green("✅ TSDown bundling completed"));
2276
+ try {
2277
+ await build(buildConfig);
2278
+ console.log(simpleChalk.green("✅ TSDown bundling completed"));
2279
+ } catch (buildError) {
2280
+ console.error(simpleChalk.red("❌ TSDown build failed with error:"));
2281
+ console.error(buildError);
2282
+ if (buildError instanceof Error) {
2283
+ console.error(simpleChalk.red("Error message:"), buildError.message);
2284
+ console.error(simpleChalk.red("Error stack:"), buildError.stack);
2285
+ }
2286
+ throw new Error(`TSDown DXT build failed: ${buildError instanceof Error ? buildError.message : String(buildError)}`);
2287
+ }
1879
2288
  const detectedOutputFile = this.detectTsdownOutputFile(
1880
2289
  outputDir,
1881
2290
  relativeEntryPath.replace(/\.ts$/, ".js")
@@ -2134,7 +2543,7 @@ export default ${JSON.stringify(buildConfig, null, 2)};
2134
2543
  if (flag.enum) {
2135
2544
  properties2[flag.name].enum = flag.enum;
2136
2545
  }
2137
- if (flag.defaultValue !== void 0) {
2546
+ if (flag.defaultValue !== void 0 && typeof flag.defaultValue !== "function") {
2138
2547
  properties2[flag.name].default = flag.defaultValue;
2139
2548
  }
2140
2549
  if (flag.mandatory) {
@@ -2309,11 +2718,62 @@ export default ${JSON.stringify(buildConfig, null, 2)};
2309
2718
  `Could not find package.json within ${maxAttempts} directories up from ${entryPointFile}. Please ensure your entry point is within a project that has a package.json file.`
2310
2719
  );
2311
2720
  }
2721
+ /**
2722
+ * Validate dxtOptions for common mistakes and security issues
2723
+ * @param flag The flag with dxtOptions to validate
2724
+ * @param envVar The environment variable name for context
2725
+ */
2726
+ validateDxtOptions(flag, envVar) {
2727
+ const dxtOptions = flag.dxtOptions;
2728
+ if (!dxtOptions) return;
2729
+ if (dxtOptions.min !== void 0 && dxtOptions.max !== void 0) {
2730
+ if (dxtOptions.min > dxtOptions.max) {
2731
+ throw new Error(
2732
+ `Invalid dxtOptions for ${envVar}: min (${dxtOptions.min}) cannot be greater than max (${dxtOptions.max})`
2733
+ );
2734
+ }
2735
+ }
2736
+ if (dxtOptions.type !== void 0) {
2737
+ const validTypes = ["string", "directory", "file", "boolean", "number"];
2738
+ if (!validTypes.includes(dxtOptions.type)) {
2739
+ throw new Error(
2740
+ `Invalid dxtOptions.type for ${envVar}: "${dxtOptions.type}". Must be one of: ${validTypes.join(", ")}`
2741
+ );
2742
+ }
2743
+ }
2744
+ if (dxtOptions.default !== void 0 && dxtOptions.type !== void 0) {
2745
+ const defaultType = typeof dxtOptions.default;
2746
+ if (dxtOptions.type === "number" && defaultType !== "number") {
2747
+ throw new Error(
2748
+ `Invalid dxtOptions.default for ${envVar}: expected number, got ${defaultType}`
2749
+ );
2750
+ }
2751
+ if (dxtOptions.type === "boolean" && defaultType !== "boolean") {
2752
+ throw new Error(
2753
+ `Invalid dxtOptions.default for ${envVar}: expected boolean, got ${defaultType}`
2754
+ );
2755
+ }
2756
+ }
2757
+ const sensitiveKeywords = ["key", "token", "password", "secret", "auth"];
2758
+ const envLower = envVar.toLowerCase();
2759
+ const hasSensitiveKeyword = sensitiveKeywords.some((keyword2) => envLower.includes(keyword2));
2760
+ if (hasSensitiveKeyword && dxtOptions.sensitive === false) {
2761
+ console.warn(
2762
+ `⚠️ Security Warning: ${envVar} contains sensitive keyword but dxtOptions.sensitive is false`
2763
+ );
2764
+ }
2765
+ if (flag.mandatory === true && dxtOptions.sensitive !== false) {
2766
+ console.warn(
2767
+ `⚠️ Security Warning: ${envVar} is required and sensitive - consider providing a secure default or making it optional`
2768
+ );
2769
+ }
2770
+ }
2312
2771
  /**
2313
2772
  * Generate environment variables and user configuration from ArgParser flags
2314
2773
  * @returns Object containing envVars and userConfig
2315
2774
  */
2316
2775
  generateEnvAndUserConfig() {
2776
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2317
2777
  const envVars = {};
2318
2778
  const userConfig = {};
2319
2779
  const shouldBeRequired = (flag) => {
@@ -2326,23 +2786,78 @@ export default ${JSON.stringify(buildConfig, null, 2)};
2326
2786
  return false;
2327
2787
  };
2328
2788
  const shouldBeSensitive = (flag) => {
2789
+ var _a2;
2790
+ if (((_a2 = flag.dxtOptions) == null ? void 0 : _a2.sensitive) !== void 0) {
2791
+ return flag.dxtOptions.sensitive;
2792
+ }
2329
2793
  const envVar = flag.env || flag.envVar;
2330
2794
  return !!envVar;
2331
2795
  };
2796
+ const getDxtType = (flag) => {
2797
+ var _a2;
2798
+ if ((_a2 = flag.dxtOptions) == null ? void 0 : _a2.type) {
2799
+ return flag.dxtOptions.type;
2800
+ }
2801
+ if (typeof flag.type === "string") {
2802
+ const lowerType = flag.type.toLowerCase();
2803
+ if (["string", "boolean", "number"].includes(lowerType)) {
2804
+ return lowerType;
2805
+ }
2806
+ } else if (flag.type === String) {
2807
+ return "string";
2808
+ } else if (flag.type === Boolean) {
2809
+ return "boolean";
2810
+ } else if (flag.type === Number) {
2811
+ return "number";
2812
+ }
2813
+ return "string";
2814
+ };
2815
+ const getDxtTitle = (flag, envVar) => {
2816
+ var _a2;
2817
+ if ((_a2 = flag.dxtOptions) == null ? void 0 : _a2.title) {
2818
+ return flag.dxtOptions.title;
2819
+ }
2820
+ return envVar.replace(/_/g, " ").toLowerCase().replace(/\b\w/g, (l) => l.toUpperCase());
2821
+ };
2822
+ const getDxtDescription = (flag, envVar) => {
2823
+ var _a2, _b2;
2824
+ let baseDescription = flag.description || `${envVar} environment variable`;
2825
+ const defaultValue = ((_a2 = flag.dxtOptions) == null ? void 0 : _a2.default) ?? ((_b2 = flag.dxtOptions) == null ? void 0 : _b2.localDefault) ?? flag.defaultValue;
2826
+ if (defaultValue !== void 0 && typeof defaultValue !== "function") {
2827
+ baseDescription += ` (default: ${defaultValue})`;
2828
+ }
2829
+ return baseDescription;
2830
+ };
2332
2831
  const mainFlags = this.argParserInstance.flags;
2333
2832
  for (const flag of mainFlags) {
2334
2833
  const envVar = flag.env || flag.envVar;
2335
2834
  if (envVar) {
2835
+ this.validateDxtOptions(flag, envVar);
2336
2836
  envVars[envVar] = `\${user_config.${envVar}}`;
2337
- userConfig[envVar] = {
2338
- type: "string",
2339
- title: envVar.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
2340
- description: flag.description || `${envVar} environment variable`,
2837
+ const userConfigEntry = {
2838
+ type: getDxtType(flag),
2839
+ title: getDxtTitle(flag, envVar),
2840
+ description: getDxtDescription(flag, envVar),
2341
2841
  required: shouldBeRequired(flag),
2342
2842
  // Respect the flag's mandatory setting
2343
2843
  sensitive: shouldBeSensitive(flag)
2344
- // Set to sensitive if tied to ENV
2844
+ // Use dxtOptions or default logic
2345
2845
  };
2846
+ if (((_a = flag.dxtOptions) == null ? void 0 : _a.multiple) !== void 0) {
2847
+ userConfigEntry.multiple = flag.dxtOptions.multiple;
2848
+ }
2849
+ if (((_b = flag.dxtOptions) == null ? void 0 : _b.min) !== void 0) {
2850
+ userConfigEntry.min = flag.dxtOptions.min;
2851
+ }
2852
+ if (((_c = flag.dxtOptions) == null ? void 0 : _c.max) !== void 0) {
2853
+ userConfigEntry.max = flag.dxtOptions.max;
2854
+ }
2855
+ if (((_d = flag.dxtOptions) == null ? void 0 : _d.default) !== void 0 && typeof flag.dxtOptions.default !== "function") {
2856
+ userConfigEntry.default = flag.dxtOptions.default;
2857
+ } else if (((_e = flag.dxtOptions) == null ? void 0 : _e.localDefault) !== void 0 && typeof flag.dxtOptions.localDefault !== "function") {
2858
+ userConfigEntry.default = flag.dxtOptions.localDefault;
2859
+ }
2860
+ userConfig[envVar] = userConfigEntry;
2346
2861
  }
2347
2862
  }
2348
2863
  if (typeof this.argParserInstance.getTools === "function") {
@@ -2352,16 +2867,32 @@ export default ${JSON.stringify(buildConfig, null, 2)};
2352
2867
  for (const flag of toolFlags) {
2353
2868
  const envVar = flag.env || flag.envVar;
2354
2869
  if (envVar && !envVars[envVar]) {
2870
+ this.validateDxtOptions(flag, envVar);
2355
2871
  envVars[envVar] = `\${user_config.${envVar}}`;
2356
- userConfig[envVar] = {
2357
- type: "string",
2358
- title: envVar.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
2359
- description: flag.description || `${envVar} environment variable`,
2872
+ const userConfigEntry = {
2873
+ type: getDxtType(flag),
2874
+ title: getDxtTitle(flag, envVar),
2875
+ description: getDxtDescription(flag, envVar),
2360
2876
  required: shouldBeRequired(flag),
2361
2877
  // Respect the flag's mandatory setting
2362
2878
  sensitive: shouldBeSensitive(flag)
2363
- // Set to sensitive if tied to ENV
2879
+ // Use dxtOptions or default logic
2364
2880
  };
2881
+ if (((_f = flag.dxtOptions) == null ? void 0 : _f.multiple) !== void 0) {
2882
+ userConfigEntry.multiple = flag.dxtOptions.multiple;
2883
+ }
2884
+ if (((_g = flag.dxtOptions) == null ? void 0 : _g.min) !== void 0) {
2885
+ userConfigEntry.min = flag.dxtOptions.min;
2886
+ }
2887
+ if (((_h = flag.dxtOptions) == null ? void 0 : _h.max) !== void 0) {
2888
+ userConfigEntry.max = flag.dxtOptions.max;
2889
+ }
2890
+ if (((_i = flag.dxtOptions) == null ? void 0 : _i.default) !== void 0 && typeof flag.dxtOptions.default !== "function") {
2891
+ userConfigEntry.default = flag.dxtOptions.default;
2892
+ } else if (((_j = flag.dxtOptions) == null ? void 0 : _j.localDefault) !== void 0 && typeof flag.dxtOptions.localDefault !== "function") {
2893
+ userConfigEntry.default = flag.dxtOptions.localDefault;
2894
+ }
2895
+ userConfig[envVar] = userConfigEntry;
2365
2896
  }
2366
2897
  }
2367
2898
  }
@@ -2392,10 +2923,10 @@ export default ${JSON.stringify(buildConfig, null, 2)};
2392
2923
  );
2393
2924
  }
2394
2925
  const pathsMatcher = getTsconfig.createPathsMatcher(tsconfig);
2395
- if (!pathsMatcher) {
2926
+ if (!pathsMatcher || typeof pathsMatcher !== "function") {
2396
2927
  if (Boolean(process.env["DEBUG"])) {
2397
2928
  console.log(
2398
- ` <${simpleChalk.gray("ts-paths")}> Failed to create paths matcher`
2929
+ ` <${simpleChalk.gray("ts-paths")}> Failed to create paths matcher or matcher is not a function`
2399
2930
  );
2400
2931
  }
2401
2932
  } else {
@@ -3105,7 +3636,8 @@ const _FlagManager = class _FlagManager {
3105
3636
  validate: parsedFromZod["validate"],
3106
3637
  enum: parsedFromZod["enum"],
3107
3638
  mandatory: parsedFromZod["mandatory"],
3108
- env: parsedFromZod["env"]
3639
+ env: parsedFromZod["env"],
3640
+ dxtOptions: parsedFromZod["dxtOptions"]
3109
3641
  };
3110
3642
  }
3111
3643
  addFlag(flag) {
@@ -3154,97 +3686,6 @@ const _FlagManager = class _FlagManager {
3154
3686
  __flags = new WeakMap();
3155
3687
  _throwForDuplicateFlags = new WeakMap();
3156
3688
  let FlagManager = _FlagManager;
3157
- function detectEntryPoint() {
3158
- try {
3159
- if (process.argv[1] && fs__namespace.existsSync(process.argv[1])) {
3160
- return process.argv[1];
3161
- }
3162
- if (typeof require !== "undefined" && require.main && require.main.filename) {
3163
- return require.main.filename;
3164
- }
3165
- return null;
3166
- } catch {
3167
- return null;
3168
- }
3169
- }
3170
- function getEntryPointFromImportMeta(importMetaUrl) {
3171
- if (importMetaUrl.startsWith("file://")) {
3172
- return decodeURIComponent(importMetaUrl.replace("file://", ""));
3173
- }
3174
- return importMetaUrl;
3175
- }
3176
- function normalizePath(path2) {
3177
- return path2.trim();
3178
- }
3179
- function resolveLogPath(logPath, fallbackEntryPoint) {
3180
- if (typeof logPath === "string") {
3181
- const normalizedPath2 = normalizePath(logPath);
3182
- if (path__namespace.isAbsolute(normalizedPath2)) {
3183
- return normalizedPath2;
3184
- }
3185
- if (normalizedPath2.startsWith("cwd:")) {
3186
- const relativePath = normalizedPath2.slice(4);
3187
- return path__namespace.resolve(process.cwd(), relativePath);
3188
- }
3189
- const entryPoint = detectEntryPoint() || fallbackEntryPoint;
3190
- if (entryPoint) {
3191
- return path__namespace.resolve(path__namespace.dirname(entryPoint), normalizedPath2);
3192
- }
3193
- console.warn(
3194
- `Warning: Could not detect entry point for log path resolution. Using process.cwd() as fallback. Path: ${normalizedPath2}`
3195
- );
3196
- return path__namespace.resolve(process.cwd(), normalizedPath2);
3197
- }
3198
- const { path: logFilePath, relativeTo = "entry", basePath } = logPath;
3199
- const normalizedPath = normalizePath(logFilePath);
3200
- switch (relativeTo) {
3201
- case "absolute":
3202
- if (basePath) {
3203
- return path__namespace.resolve(basePath, normalizedPath);
3204
- }
3205
- if (path__namespace.isAbsolute(normalizedPath)) {
3206
- return normalizedPath;
3207
- }
3208
- console.warn(
3209
- `Warning: relativeTo 'absolute' specified but no basePath provided and path is not absolute. Using process.cwd() as fallback. Path: ${normalizedPath}`
3210
- );
3211
- return path__namespace.resolve(process.cwd(), normalizedPath);
3212
- case "cwd":
3213
- return path__namespace.resolve(process.cwd(), normalizedPath);
3214
- case "entry":
3215
- default:
3216
- const entryPoint = detectEntryPoint() || fallbackEntryPoint;
3217
- if (entryPoint) {
3218
- return path__namespace.resolve(path__namespace.dirname(entryPoint), normalizedPath);
3219
- }
3220
- console.warn(
3221
- `Warning: Could not detect entry point for log path resolution. Using process.cwd() as fallback. Path: ${normalizedPath}`
3222
- );
3223
- return path__namespace.resolve(process.cwd(), normalizedPath);
3224
- }
3225
- }
3226
- function entryRelative(path2) {
3227
- return {
3228
- path: path2,
3229
- relativeTo: "entry"
3230
- };
3231
- }
3232
- function cwdRelative(path2) {
3233
- return {
3234
- path: path2,
3235
- relativeTo: "cwd"
3236
- };
3237
- }
3238
- function absolutePath(path2, basePath) {
3239
- return {
3240
- path: path2,
3241
- relativeTo: "absolute",
3242
- basePath
3243
- };
3244
- }
3245
- function legacyCwdPath(path2) {
3246
- return `cwd:${path2}`;
3247
- }
3248
3689
  class ArgParserError extends Error {
3249
3690
  constructor(message, cmdChain = []) {
3250
3691
  super(message);
@@ -25030,6 +25471,7 @@ exports.ArgParserFuzzyTester = ArgParserFuzzyTester;
25030
25471
  exports.ArgParserMcp = ArgParserMcp;
25031
25472
  exports.ConfigPlugin = ConfigPlugin;
25032
25473
  exports.ConfigPluginRegistry = ConfigPluginRegistry;
25474
+ exports.DxtPathResolver = DxtPathResolver;
25033
25475
  exports.EnvConfigPlugin = EnvConfigPlugin;
25034
25476
  exports.JsonConfigPlugin = JsonConfigPlugin;
25035
25477
  exports.OutputSchemaPatterns = OutputSchemaPatterns;
@@ -25064,5 +25506,6 @@ exports.isValidMcpToolName = isValidMcpToolName;
25064
25506
  exports.legacyCwdPath = legacyCwdPath;
25065
25507
  exports.resolveLogPath = resolveLogPath;
25066
25508
  exports.sanitizeMcpToolName = sanitizeMcpToolName;
25509
+ exports.zodDxtOptionsSchema = zodDxtOptionsSchema;
25067
25510
  exports.zodFlagSchema = zodFlagSchema;
25068
25511
  //# sourceMappingURL=index.cjs.map