kly 0.1.0 → 0.1.1

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.
@@ -0,0 +1,3 @@
1
+ import { n as formatPermissionsSummary, t as buildSandboxConfig } from "./kly.mjs";
2
+
3
+ export { buildSandboxConfig, formatPermissionsSummary };
package/dist/bin/kly.mjs CHANGED
@@ -1851,14 +1851,32 @@ const PROTECTED_PATHS = {
1851
1851
  alwaysDenyRead: [join(homedir(), ".kly")]
1852
1852
  };
1853
1853
  /**
1854
+ * Resolve filesystem path with special marker support
1855
+ *
1856
+ * Special markers:
1857
+ * - "*": User's home directory (allows access to all non-sensitive files)
1858
+ * - Absolute paths: Used as-is
1859
+ *
1860
+ * @param path - Path to resolve (may contain special markers)
1861
+ * @returns Resolved absolute path, or undefined if path is undefined
1862
+ */
1863
+ function resolveFilesystemPath(path) {
1864
+ if (!path) return void 0;
1865
+ if (path === "*") return homedir();
1866
+ return path;
1867
+ }
1868
+ /**
1854
1869
  * Build a complete SandboxRuntimeConfig from declared app permissions
1855
1870
  *
1856
1871
  * This merges:
1857
1872
  * 1. Default safe configuration
1858
1873
  * 2. Automatic LLM domains (if apiKeys: true)
1859
- * 3. User-declared sandbox config
1874
+ * 3. User-declared sandbox config (with special marker support)
1860
1875
  * 4. Mandatory protections (always applied)
1861
1876
  *
1877
+ * Special markers in filesystem paths:
1878
+ * - "*": Allows access to all files in user's home directory (except sensitive paths)
1879
+ *
1862
1880
  * @param permissions - Declared app permissions
1863
1881
  * @returns Complete sandbox configuration ready for SandboxManager
1864
1882
  */
@@ -1870,10 +1888,16 @@ function buildSandboxConfig(permissions) {
1870
1888
  if (permissions?.apiKeys) allowedDomains = [...LLM_API_DOMAINS];
1871
1889
  if (permissions?.sandbox) {
1872
1890
  const userSandbox = permissions.sandbox;
1873
- if (userSandbox.network?.allowedDomains) allowedDomains = [...allowedDomains, ...userSandbox.network.allowedDomains];
1891
+ if (userSandbox.network?.allowedDomains) {
1892
+ const domains = userSandbox.network.allowedDomains.filter((d) => d !== void 0);
1893
+ allowedDomains = [...allowedDomains, ...domains];
1894
+ }
1874
1895
  if (userSandbox.filesystem) {
1875
- if (userSandbox.filesystem.allowWrite) allowWrite = userSandbox.filesystem.allowWrite;
1876
- if (userSandbox.filesystem.denyRead) denyRead = [...denyRead, ...userSandbox.filesystem.denyRead];
1896
+ if (userSandbox.filesystem.allowWrite) allowWrite = userSandbox.filesystem.allowWrite.map(resolveFilesystemPath).filter((p) => p !== void 0);
1897
+ if (userSandbox.filesystem.denyRead) {
1898
+ const deniedPaths = userSandbox.filesystem.denyRead.map(resolveFilesystemPath).filter((p) => p !== void 0);
1899
+ denyRead = [...denyRead, ...deniedPaths];
1900
+ }
1877
1901
  }
1878
1902
  }
1879
1903
  return {
@@ -1904,9 +1928,13 @@ function formatPermissionsSummary(permissions) {
1904
1928
  summary.push(`• Network: ${domains}${more}`);
1905
1929
  }
1906
1930
  if (config.filesystem.allowWrite.length > 1 || config.filesystem.allowWrite.length === 1 && config.filesystem.allowWrite[0] !== currentDir) {
1907
- const dirs = config.filesystem.allowWrite.map((p) => p === currentDir ? "current directory" : p).slice(0, 2).join(", ");
1908
- const more = config.filesystem.allowWrite.length > 2 ? ` +${config.filesystem.allowWrite.length - 2} more` : "";
1909
- summary.push(`• Filesystem write: ${dirs}${more}`);
1931
+ const homeDir = homedir();
1932
+ if (config.filesystem.allowWrite.includes(homeDir)) summary.push("• Filesystem write: All non-sensitive directories");
1933
+ else {
1934
+ const dirs = config.filesystem.allowWrite.map((p) => p === currentDir ? "current directory" : p).slice(0, 2).join(", ");
1935
+ const more = config.filesystem.allowWrite.length > 2 ? ` +${config.filesystem.allowWrite.length - 2} more` : "";
1936
+ summary.push(`• Filesystem write: ${dirs}${more}`);
1937
+ }
1910
1938
  }
1911
1939
  if (permissions?.sandbox?.filesystem?.denyRead) summary.push(`• Filesystem read denied: ${permissions.sandbox.filesystem.denyRead.length} path(s)`);
1912
1940
  return summary;
@@ -2703,19 +2731,38 @@ async function executeApp(ref, repoPath, args$1, mcp) {
2703
2731
  const prevRemoteRef = process.env[ENV_VARS.REMOTE_REF];
2704
2732
  process.env[ENV_VARS.REMOTE_REF] = remoteRef;
2705
2733
  try {
2706
- const { getAppIdentifier: getAppIdentifier$1, checkApiKeyPermission: checkApiKeyPermission$1, getAppSandboxConfig: getAppSandboxConfig$1 } = await import("./permissions-2r_7ZqaH.mjs");
2707
- const { launchSandbox: launchSandbox$1 } = await import("./launcher-vTpgdO9n.mjs");
2734
+ const { getAppIdentifier: getAppIdentifier$1, checkApiKeyPermission: checkApiKeyPermission$1, getAppSandboxConfig: getAppSandboxConfig$1 } = await import("./permissions-C_WgoA3t.mjs");
2735
+ const { launchSandbox: launchSandbox$1 } = await import("./launcher-Ex3ynZdE.mjs");
2736
+ const { buildSandboxConfig: buildSandboxConfig$1, formatPermissionsSummary: formatPermissionsSummary$1 } = await import("./config-builder-D5EtwOB3.mjs");
2737
+ const { extractAppPermissions: extractAppPermissions$1 } = await import("./permissions-extractor-BfUPS0Tr.mjs");
2708
2738
  const appId = getAppIdentifier$1();
2739
+ console.log("📋 Reading app permissions...");
2740
+ const declaredPermissions = await extractAppPermissions$1(absoluteEntryPath);
2741
+ if (declaredPermissions) {
2742
+ const summary = formatPermissionsSummary$1(declaredPermissions);
2743
+ if (summary.length > 0) {
2744
+ console.log("\nThis app requests the following permissions:");
2745
+ for (const item of summary) console.log(item);
2746
+ console.log("");
2747
+ }
2748
+ }
2709
2749
  console.log("🔐 Checking permissions...");
2710
- const allowApiKey = await checkApiKeyPermission$1(appId);
2711
- if (!allowApiKey) {
2712
- console.error("❌ Permission denied: API key access rejected");
2713
- process.exit(1);
2750
+ let allowApiKey = false;
2751
+ let sandboxConfig = null;
2752
+ if (declaredPermissions?.apiKeys) {
2753
+ allowApiKey = await checkApiKeyPermission$1(appId);
2754
+ if (!allowApiKey) {
2755
+ console.error("❌ Permission denied: API key access rejected");
2756
+ process.exit(1);
2757
+ }
2714
2758
  }
2715
- const sandboxConfig = await getAppSandboxConfig$1(appId);
2716
- if (!sandboxConfig) {
2717
- console.error("❌ Permission denied: Sandbox configuration rejected");
2718
- process.exit(1);
2759
+ if (declaredPermissions) sandboxConfig = buildSandboxConfig$1(declaredPermissions);
2760
+ else {
2761
+ sandboxConfig = await getAppSandboxConfig$1(appId);
2762
+ if (!sandboxConfig) {
2763
+ console.error("❌ Permission denied: Sandbox configuration rejected");
2764
+ process.exit(1);
2765
+ }
2719
2766
  }
2720
2767
  if (mcp) {
2721
2768
  console.warn("⚠️ MCP mode with remote repos not yet fully supported in new architecture");
@@ -2884,5 +2931,5 @@ main().catch((err) => {
2884
2931
  });
2885
2932
 
2886
2933
  //#endregion
2887
- export { getAppSandboxConfig as a, revokePermission as c, getAppName as i, savePermissions as l, clearAllPermissions as n, listPermissions as o, getAppIdentifier as r, loadPermissions as s, checkApiKeyPermission as t, launchSandbox as u };
2934
+ export { getAppIdentifier as a, listPermissions as c, savePermissions as d, launchSandbox as f, clearAllPermissions as i, loadPermissions as l, formatPermissionsSummary as n, getAppName as o, checkApiKeyPermission as r, getAppSandboxConfig as s, buildSandboxConfig as t, revokePermission as u };
2888
2935
  //# sourceMappingURL=kly.mjs.map