kly 0.3.0 → 0.3.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.
Files changed (36) hide show
  1. package/README.md +14 -2
  2. package/dist/ai/context.mjs.map +1 -1
  3. package/dist/ai/storage.mjs.map +1 -1
  4. package/dist/bin/bin-registry-Cj1PddZ1.mjs +3 -0
  5. package/dist/bin/kly.mjs +56 -37
  6. package/dist/bin/kly.mjs.map +1 -1
  7. package/dist/bin/{permissions-extractor-ySRyhQut.mjs → permissions-extractor-B3XI8JLv.mjs} +2 -2
  8. package/dist/bin/{permissions-extractor-ySRyhQut.mjs.map → permissions-extractor-B3XI8JLv.mjs.map} +1 -1
  9. package/dist/cli.mjs.map +1 -1
  10. package/dist/define-app.mjs.map +1 -1
  11. package/dist/mcp/schema-converter.mjs.map +1 -1
  12. package/dist/mcp/server.d.mts.map +1 -1
  13. package/dist/mcp/server.mjs.map +1 -1
  14. package/dist/permissions/index.mjs.map +1 -1
  15. package/dist/sandbox/bundled-executor.mjs.map +1 -1
  16. package/dist/sandbox/ipc-client.mjs.map +1 -1
  17. package/dist/sandbox/sandboxed-context.mjs.map +1 -1
  18. package/dist/tool.d.mts.map +1 -1
  19. package/dist/tool.mjs.map +1 -1
  20. package/dist/types.d.mts.map +1 -1
  21. package/dist/types.mjs.map +1 -1
  22. package/dist/ui/components/confirm.d.mts.map +1 -1
  23. package/dist/ui/components/confirm.mjs.map +1 -1
  24. package/dist/ui/components/form.d.mts.map +1 -1
  25. package/dist/ui/components/form.mjs.map +1 -1
  26. package/dist/ui/components/table.d.mts.map +1 -1
  27. package/dist/ui/components/table.mjs.map +1 -1
  28. package/dist/ui/utils/colors.d.mts.map +1 -1
  29. package/dist/ui/utils/colors.mjs.map +1 -1
  30. package/dist/ui/utils/tty.mjs.map +1 -1
  31. package/package.json +17 -16
  32. package/dist/bin/bin-registry-DOBspniG.mjs +0 -3
  33. package/dist/bin/remote-tQeFZX9o.mjs +0 -3
  34. /package/dist/bin/{config-builder-VSUaGlaV.mjs → config-builder-CkkAqWMY.mjs} +0 -0
  35. /package/dist/bin/{launcher-DD6vpEFb.mjs → launcher-CSdy4_ZV.mjs} +0 -0
  36. /package/dist/bin/{permissions-D7-M2lRi.mjs → permissions-DOOzghc5.mjs} +0 -0
package/README.md CHANGED
@@ -2,8 +2,20 @@
2
2
 
3
3
  [![NPM version](https://img.shields.io/npm/v/kly?color=a1b858&label=)](https://www.npmjs.com/package/kly)
4
4
 
5
- ```ts
6
- const a = 1
5
+ A CLI framework with sandbox isolation and MCP support.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ bun install -g kly
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ kly run ./app.ts # Run local app
17
+ kly run user/repo # Run remote app
18
+ kly mcp ./app.ts # Run as MCP server
7
19
  ```
8
20
 
9
21
  ## License
@@ -1 +1 @@
1
- {"version":3,"file":"context.mjs","names":[],"sources":["../../src/ai/context.ts"],"sourcesContent":["import { checkApiKeyPermission, getAppIdentifier } from \"../permissions\";\nimport type { ModelConfig, ModelInfo, ModelsContext } from \"../types\";\nimport { getCurrentModelConfig, listModels } from \"./storage\";\n\n/**\n * Create models context for ExecuteContext\n * Provides access to configured LLM models and their credentials (with permission checks)\n */\nexport function createModelsContext(): ModelsContext {\n // Track if permission has been checked in this process\n let permissionChecked = false;\n let permissionGranted = false;\n\n /**\n * Check permission before allowing access to API keys\n */\n async function ensurePermission(): Promise<void> {\n if (permissionChecked) {\n if (!permissionGranted) {\n throw new Error(\n \"Permission denied: This app does not have permission to access API keys.\",\n );\n }\n return;\n }\n\n const appId = getAppIdentifier();\n permissionGranted = await checkApiKeyPermission(appId);\n permissionChecked = true;\n\n if (!permissionGranted) {\n throw new Error(\n \"Permission denied: This app does not have permission to access API keys.\",\n );\n }\n }\n\n return {\n list(): ModelInfo[] {\n return listModels().map((m) => ({\n name: m.name,\n provider: m.config.provider,\n model: m.config.model,\n isCurrent: m.isCurrent,\n }));\n },\n\n getCurrent(): ModelInfo | null {\n const models = listModels();\n const current = models.find((m) => m.isCurrent);\n if (!current) return null;\n\n return {\n name: current.name,\n provider: current.config.provider,\n model: current.config.model,\n isCurrent: true,\n };\n },\n\n get(name: string): ModelInfo | null {\n const models = listModels();\n const found = models.find((m) => m.name === name);\n if (!found) return null;\n\n return {\n name: found.name,\n provider: found.config.provider,\n model: found.config.model,\n isCurrent: found.isCurrent,\n };\n },\n\n async getConfigAsync(name?: string): Promise<ModelConfig | null> {\n // Check permission first\n await ensurePermission();\n\n if (name) {\n const models = listModels();\n const found = models.find((m) => m.name === name);\n if (!found) return null;\n\n return {\n provider: found.config.provider,\n model: found.config.model,\n apiKey: found.config.apiKey,\n baseURL: found.config.baseURL,\n };\n }\n\n const current = getCurrentModelConfig();\n if (!current) return null;\n\n return {\n provider: current.provider,\n model: current.model,\n apiKey: current.apiKey,\n baseURL: current.baseURL,\n };\n },\n };\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,sBAAqC;CAEnD,IAAI,oBAAoB;CACxB,IAAI,oBAAoB;;;;CAKxB,eAAe,mBAAkC;AAC/C,MAAI,mBAAmB;AACrB,OAAI,CAAC,kBACH,OAAM,IAAI,MACR,2EACD;AAEH;;AAIF,sBAAoB,MAAM,sBADZ,kBAAkB,CACsB;AACtD,sBAAoB;AAEpB,MAAI,CAAC,kBACH,OAAM,IAAI,MACR,2EACD;;AAIL,QAAO;EACL,OAAoB;AAClB,UAAO,YAAY,CAAC,KAAK,OAAO;IAC9B,MAAM,EAAE;IACR,UAAU,EAAE,OAAO;IACnB,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE;IACd,EAAE;;EAGL,aAA+B;GAE7B,MAAM,UADS,YAAY,CACJ,MAAM,MAAM,EAAE,UAAU;AAC/C,OAAI,CAAC,QAAS,QAAO;AAErB,UAAO;IACL,MAAM,QAAQ;IACd,UAAU,QAAQ,OAAO;IACzB,OAAO,QAAQ,OAAO;IACtB,WAAW;IACZ;;EAGH,IAAI,MAAgC;GAElC,MAAM,QADS,YAAY,CACN,MAAM,MAAM,EAAE,SAAS,KAAK;AACjD,OAAI,CAAC,MAAO,QAAO;AAEnB,UAAO;IACL,MAAM,MAAM;IACZ,UAAU,MAAM,OAAO;IACvB,OAAO,MAAM,OAAO;IACpB,WAAW,MAAM;IAClB;;EAGH,MAAM,eAAe,MAA4C;AAE/D,SAAM,kBAAkB;AAExB,OAAI,MAAM;IAER,MAAM,QADS,YAAY,CACN,MAAM,MAAM,EAAE,SAAS,KAAK;AACjD,QAAI,CAAC,MAAO,QAAO;AAEnB,WAAO;KACL,UAAU,MAAM,OAAO;KACvB,OAAO,MAAM,OAAO;KACpB,QAAQ,MAAM,OAAO;KACrB,SAAS,MAAM,OAAO;KACvB;;GAGH,MAAM,UAAU,uBAAuB;AACvC,OAAI,CAAC,QAAS,QAAO;AAErB,UAAO;IACL,UAAU,QAAQ;IAClB,OAAO,QAAQ;IACf,QAAQ,QAAQ;IAChB,SAAS,QAAQ;IAClB;;EAEJ"}
1
+ {"version":3,"file":"context.mjs","names":[],"sources":["../../src/ai/context.ts"],"sourcesContent":["import { checkApiKeyPermission, getAppIdentifier } from \"../permissions\";\nimport type { ModelConfig, ModelInfo, ModelsContext } from \"../types\";\nimport { getCurrentModelConfig, listModels } from \"./storage\";\n\n/**\n * Create models context for ExecuteContext\n * Provides access to configured LLM models and their credentials (with permission checks)\n */\nexport function createModelsContext(): ModelsContext {\n // Track if permission has been checked in this process\n let permissionChecked = false;\n let permissionGranted = false;\n\n /**\n * Check permission before allowing access to API keys\n */\n async function ensurePermission(): Promise<void> {\n if (permissionChecked) {\n if (!permissionGranted) {\n throw new Error(\"Permission denied: This app does not have permission to access API keys.\");\n }\n return;\n }\n\n const appId = getAppIdentifier();\n permissionGranted = await checkApiKeyPermission(appId);\n permissionChecked = true;\n\n if (!permissionGranted) {\n throw new Error(\"Permission denied: This app does not have permission to access API keys.\");\n }\n }\n\n return {\n list(): ModelInfo[] {\n return listModels().map((m) => ({\n name: m.name,\n provider: m.config.provider,\n model: m.config.model,\n isCurrent: m.isCurrent,\n }));\n },\n\n getCurrent(): ModelInfo | null {\n const models = listModels();\n const current = models.find((m) => m.isCurrent);\n if (!current) return null;\n\n return {\n name: current.name,\n provider: current.config.provider,\n model: current.config.model,\n isCurrent: true,\n };\n },\n\n get(name: string): ModelInfo | null {\n const models = listModels();\n const found = models.find((m) => m.name === name);\n if (!found) return null;\n\n return {\n name: found.name,\n provider: found.config.provider,\n model: found.config.model,\n isCurrent: found.isCurrent,\n };\n },\n\n async getConfigAsync(name?: string): Promise<ModelConfig | null> {\n // Check permission first\n await ensurePermission();\n\n if (name) {\n const models = listModels();\n const found = models.find((m) => m.name === name);\n if (!found) return null;\n\n return {\n provider: found.config.provider,\n model: found.config.model,\n apiKey: found.config.apiKey,\n baseURL: found.config.baseURL,\n };\n }\n\n const current = getCurrentModelConfig();\n if (!current) return null;\n\n return {\n provider: current.provider,\n model: current.model,\n apiKey: current.apiKey,\n baseURL: current.baseURL,\n };\n },\n };\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,sBAAqC;CAEnD,IAAI,oBAAoB;CACxB,IAAI,oBAAoB;;;;CAKxB,eAAe,mBAAkC;AAC/C,MAAI,mBAAmB;AACrB,OAAI,CAAC,kBACH,OAAM,IAAI,MAAM,2EAA2E;AAE7F;;AAIF,sBAAoB,MAAM,sBADZ,kBAAkB,CACsB;AACtD,sBAAoB;AAEpB,MAAI,CAAC,kBACH,OAAM,IAAI,MAAM,2EAA2E;;AAI/F,QAAO;EACL,OAAoB;AAClB,UAAO,YAAY,CAAC,KAAK,OAAO;IAC9B,MAAM,EAAE;IACR,UAAU,EAAE,OAAO;IACnB,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE;IACd,EAAE;;EAGL,aAA+B;GAE7B,MAAM,UADS,YAAY,CACJ,MAAM,MAAM,EAAE,UAAU;AAC/C,OAAI,CAAC,QAAS,QAAO;AAErB,UAAO;IACL,MAAM,QAAQ;IACd,UAAU,QAAQ,OAAO;IACzB,OAAO,QAAQ,OAAO;IACtB,WAAW;IACZ;;EAGH,IAAI,MAAgC;GAElC,MAAM,QADS,YAAY,CACN,MAAM,MAAM,EAAE,SAAS,KAAK;AACjD,OAAI,CAAC,MAAO,QAAO;AAEnB,UAAO;IACL,MAAM,MAAM;IACZ,UAAU,MAAM,OAAO;IACvB,OAAO,MAAM,OAAO;IACpB,WAAW,MAAM;IAClB;;EAGH,MAAM,eAAe,MAA4C;AAE/D,SAAM,kBAAkB;AAExB,OAAI,MAAM;IAER,MAAM,QADS,YAAY,CACN,MAAM,MAAM,EAAE,SAAS,KAAK;AACjD,QAAI,CAAC,MAAO,QAAO;AAEnB,WAAO;KACL,UAAU,MAAM,OAAO;KACvB,OAAO,MAAM,OAAO;KACpB,QAAQ,MAAM,OAAO;KACrB,SAAS,MAAM,OAAO;KACvB;;GAGH,MAAM,UAAU,uBAAuB;AACvC,OAAI,CAAC,QAAS,QAAO;AAErB,UAAO;IACL,UAAU,QAAQ;IAClB,OAAO,QAAQ;IACf,QAAQ,QAAQ;IAChB,SAAS,QAAQ;IAClB;;EAEJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"storage.mjs","names":[],"sources":["../../src/ai/storage.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { error } from \"../ui\";\nimport type { LLMConfig, LLMProvider } from \"./types\";\n\nconst CONFIG_DIR = join(homedir(), \".kly\");\nconst CONFIG_FILE = join(CONFIG_DIR, \"config.json\");\n\nexport interface KlyConfig {\n currentModel?: string;\n models: Record<string, LLMConfig>;\n}\n\n/**\n * Ensure config directory exists\n */\nfunction ensureConfigDir(): void {\n if (!existsSync(CONFIG_DIR)) {\n mkdirSync(CONFIG_DIR, { recursive: true });\n }\n}\n\n/**\n * Load configuration from ~/.kly/config.json\n */\nexport function loadConfig(): KlyConfig {\n ensureConfigDir();\n\n if (!existsSync(CONFIG_FILE)) {\n return { models: {} };\n }\n\n try {\n const content = readFileSync(CONFIG_FILE, \"utf-8\");\n return JSON.parse(content);\n } catch (err) {\n error(`Failed to parse config file: ${err}`);\n return { models: {} };\n }\n}\n\n/**\n * Save configuration to ~/.kly/config.json\n */\nexport function saveConfig(config: KlyConfig): void {\n ensureConfigDir();\n writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), \"utf-8\");\n}\n\n/**\n * Get current active model configuration\n */\nexport function getCurrentModelConfig(): LLMConfig | null {\n const config = loadConfig();\n\n if (!config.currentModel) {\n return null;\n }\n\n return config.models[config.currentModel] || null;\n}\n\n/**\n * Set a model as current\n */\nexport function setCurrentModel(modelName: string): void {\n const config = loadConfig();\n\n if (!config.models[modelName]) {\n throw new Error(`Model '${modelName}' not found in config`);\n }\n\n config.currentModel = modelName;\n saveConfig(config);\n}\n\n/**\n * Add or update a model configuration\n */\nexport function saveModelConfig(\n modelName: string,\n modelConfig: LLMConfig,\n): void {\n const config = loadConfig();\n\n config.models[modelName] = modelConfig;\n\n // Set as current if it's the first model\n if (!config.currentModel) {\n config.currentModel = modelName;\n }\n\n saveConfig(config);\n}\n\n/**\n * Remove a model configuration\n */\nexport function removeModelConfig(modelName: string): void {\n const config = loadConfig();\n\n delete config.models[modelName];\n\n // Clear current if it was removed\n if (config.currentModel === modelName) {\n config.currentModel = undefined;\n }\n\n saveConfig(config);\n}\n\n/**\n * List all configured models\n */\nexport function listModels(): Array<{\n name: string;\n config: LLMConfig;\n isCurrent: boolean;\n}> {\n const config = loadConfig();\n\n return Object.entries(config.models).map(([name, modelConfig]) => ({\n name,\n config: modelConfig,\n isCurrent: name === config.currentModel,\n }));\n}\n\n/**\n * Get provider display name\n */\nexport function getProviderDisplayName(provider: LLMProvider): string {\n const displayNames: Record<LLMProvider, string> = {\n openai: \"OpenAI\",\n anthropic: \"Anthropic\",\n google: \"Google\",\n deepseek: \"DeepSeek\",\n ollama: \"Ollama\",\n groq: \"Groq\",\n mistral: \"Mistral\",\n cohere: \"Cohere\",\n \"openai-compatible\": \"OpenAI Compatible\",\n };\n return displayNames[provider];\n}\n"],"mappings":";;;;;;AAMA,MAAM,aAAa,KAAK,SAAS,EAAE,OAAO;AAC1C,MAAM,cAAc,KAAK,YAAY,cAAc;;;;AAUnD,SAAS,kBAAwB;AAC/B,KAAI,CAAC,WAAW,WAAW,CACzB,WAAU,YAAY,EAAE,WAAW,MAAM,CAAC;;;;;AAO9C,SAAgB,aAAwB;AACtC,kBAAiB;AAEjB,KAAI,CAAC,WAAW,YAAY,CAC1B,QAAO,EAAE,QAAQ,EAAE,EAAE;AAGvB,KAAI;EACF,MAAM,UAAU,aAAa,aAAa,QAAQ;AAClD,SAAO,KAAK,MAAM,QAAQ;UACnB,KAAK;AACZ,QAAM,gCAAgC,MAAM;AAC5C,SAAO,EAAE,QAAQ,EAAE,EAAE;;;;;;AAezB,SAAgB,wBAA0C;CACxD,MAAM,SAAS,YAAY;AAE3B,KAAI,CAAC,OAAO,aACV,QAAO;AAGT,QAAO,OAAO,OAAO,OAAO,iBAAiB;;;;;AAuD/C,SAAgB,aAIb;CACD,MAAM,SAAS,YAAY;AAE3B,QAAO,OAAO,QAAQ,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,kBAAkB;EACjE;EACA,QAAQ;EACR,WAAW,SAAS,OAAO;EAC5B,EAAE"}
1
+ {"version":3,"file":"storage.mjs","names":[],"sources":["../../src/ai/storage.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { error } from \"../ui\";\nimport type { LLMConfig, LLMProvider } from \"./types\";\n\nconst CONFIG_DIR = join(homedir(), \".kly\");\nconst CONFIG_FILE = join(CONFIG_DIR, \"config.json\");\n\nexport interface KlyConfig {\n currentModel?: string;\n models: Record<string, LLMConfig>;\n}\n\n/**\n * Ensure config directory exists\n */\nfunction ensureConfigDir(): void {\n if (!existsSync(CONFIG_DIR)) {\n mkdirSync(CONFIG_DIR, { recursive: true });\n }\n}\n\n/**\n * Load configuration from ~/.kly/config.json\n */\nexport function loadConfig(): KlyConfig {\n ensureConfigDir();\n\n if (!existsSync(CONFIG_FILE)) {\n return { models: {} };\n }\n\n try {\n const content = readFileSync(CONFIG_FILE, \"utf-8\");\n return JSON.parse(content);\n } catch (err) {\n error(`Failed to parse config file: ${err}`);\n return { models: {} };\n }\n}\n\n/**\n * Save configuration to ~/.kly/config.json\n */\nexport function saveConfig(config: KlyConfig): void {\n ensureConfigDir();\n writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), \"utf-8\");\n}\n\n/**\n * Get current active model configuration\n */\nexport function getCurrentModelConfig(): LLMConfig | null {\n const config = loadConfig();\n\n if (!config.currentModel) {\n return null;\n }\n\n return config.models[config.currentModel] || null;\n}\n\n/**\n * Set a model as current\n */\nexport function setCurrentModel(modelName: string): void {\n const config = loadConfig();\n\n if (!config.models[modelName]) {\n throw new Error(`Model '${modelName}' not found in config`);\n }\n\n config.currentModel = modelName;\n saveConfig(config);\n}\n\n/**\n * Add or update a model configuration\n */\nexport function saveModelConfig(modelName: string, modelConfig: LLMConfig): void {\n const config = loadConfig();\n\n config.models[modelName] = modelConfig;\n\n // Set as current if it's the first model\n if (!config.currentModel) {\n config.currentModel = modelName;\n }\n\n saveConfig(config);\n}\n\n/**\n * Remove a model configuration\n */\nexport function removeModelConfig(modelName: string): void {\n const config = loadConfig();\n\n delete config.models[modelName];\n\n // Clear current if it was removed\n if (config.currentModel === modelName) {\n config.currentModel = undefined;\n }\n\n saveConfig(config);\n}\n\n/**\n * List all configured models\n */\nexport function listModels(): Array<{\n name: string;\n config: LLMConfig;\n isCurrent: boolean;\n}> {\n const config = loadConfig();\n\n return Object.entries(config.models).map(([name, modelConfig]) => ({\n name,\n config: modelConfig,\n isCurrent: name === config.currentModel,\n }));\n}\n\n/**\n * Get provider display name\n */\nexport function getProviderDisplayName(provider: LLMProvider): string {\n const displayNames: Record<LLMProvider, string> = {\n openai: \"OpenAI\",\n anthropic: \"Anthropic\",\n google: \"Google\",\n deepseek: \"DeepSeek\",\n ollama: \"Ollama\",\n groq: \"Groq\",\n mistral: \"Mistral\",\n cohere: \"Cohere\",\n \"openai-compatible\": \"OpenAI Compatible\",\n };\n return displayNames[provider];\n}\n"],"mappings":";;;;;;AAMA,MAAM,aAAa,KAAK,SAAS,EAAE,OAAO;AAC1C,MAAM,cAAc,KAAK,YAAY,cAAc;;;;AAUnD,SAAS,kBAAwB;AAC/B,KAAI,CAAC,WAAW,WAAW,CACzB,WAAU,YAAY,EAAE,WAAW,MAAM,CAAC;;;;;AAO9C,SAAgB,aAAwB;AACtC,kBAAiB;AAEjB,KAAI,CAAC,WAAW,YAAY,CAC1B,QAAO,EAAE,QAAQ,EAAE,EAAE;AAGvB,KAAI;EACF,MAAM,UAAU,aAAa,aAAa,QAAQ;AAClD,SAAO,KAAK,MAAM,QAAQ;UACnB,KAAK;AACZ,QAAM,gCAAgC,MAAM;AAC5C,SAAO,EAAE,QAAQ,EAAE,EAAE;;;;;;AAezB,SAAgB,wBAA0C;CACxD,MAAM,SAAS,YAAY;AAE3B,KAAI,CAAC,OAAO,aACV,QAAO;AAGT,QAAO,OAAO,OAAO,OAAO,iBAAiB;;;;;AAoD/C,SAAgB,aAIb;CACD,MAAM,SAAS,YAAY;AAE3B,QAAO,OAAO,QAAQ,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,kBAAkB;EACjE;EACA,QAAQ;EACR,WAAW,SAAS,OAAO;EAC5B,EAAE"}
@@ -0,0 +1,3 @@
1
+ import { A as writeRegistry, C as removeShim, D as listCommands, E as getRegistryPath, M as isCommandAvailable, O as readRegistry, S as getShimDir, T as getCommand, _ as autoRegisterBins, b as createShim, g as setupPath, h as isKlyBinInPath, j as detectBins, k as removeCommand, m as getShellConfigFile, p as checkPathSetup, v as shouldReregisterLocal, w as addCommand, x as generateShimPath, y as unregisterCommand } from "./kly.mjs";
2
+
3
+ export { autoRegisterBins };
package/dist/bin/kly.mjs CHANGED
@@ -619,7 +619,7 @@ async function fetchModelsDevData(forceRefresh = false) {
619
619
  if (!forceRefresh && existsSync(CACHE_FILE)) try {
620
620
  const cached = JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
621
621
  if (Date.now() - cached.timestamp < CACHE_TTL) return cached;
622
- } catch (_error) {}
622
+ } catch {}
623
623
  try {
624
624
  const response = await fetch(MODELS_DEV_API);
625
625
  if (!response.ok) return null;
@@ -629,9 +629,9 @@ async function fetchModelsDevData(forceRefresh = false) {
629
629
  };
630
630
  try {
631
631
  writeFileSync(CACHE_FILE, JSON.stringify(cachedData, null, 2), "utf-8");
632
- } catch (_error) {}
632
+ } catch {}
633
633
  return cachedData;
634
- } catch (_error) {
634
+ } catch {
635
635
  if (existsSync(CACHE_FILE)) try {
636
636
  return JSON.parse(readFileSync(CACHE_FILE, "utf-8"));
637
637
  } catch {}
@@ -2270,7 +2270,7 @@ async function checkForUpdates(ref, metadata) {
2270
2270
  //#region src/remote/index.ts
2271
2271
  init_parser();
2272
2272
  /** Current kly CLI version */
2273
- const KLY_VERSION = "0.3.0";
2273
+ const KLY_VERSION = "0.3.1";
2274
2274
  /**
2275
2275
  * Run a remote GitHub repository as a kly app
2276
2276
  */
@@ -2302,7 +2302,7 @@ async function runRemote(input, options = {}) {
2302
2302
  await installDependencies(repoPath);
2303
2303
  }
2304
2304
  if (!options.skipRegister) {
2305
- const { autoRegisterBins: autoRegisterBins$1 } = await import("./bin-registry-DOBspniG.mjs");
2305
+ const { autoRegisterBins: autoRegisterBins$1 } = await import("./bin-registry-Cj1PddZ1.mjs");
2306
2306
  await autoRegisterBins$1(repoPath, {
2307
2307
  type: "remote",
2308
2308
  remoteRef: formatRepoUrl(ref),
@@ -2455,10 +2455,10 @@ async function executeApp(ref, repoPath, args$1, mcp) {
2455
2455
  const prevRemoteRef = process.env[ENV_VARS.REMOTE_REF];
2456
2456
  process.env[ENV_VARS.REMOTE_REF] = remoteRef;
2457
2457
  try {
2458
- const { getAppIdentifier: getAppIdentifier$1, checkApiKeyPermission: checkApiKeyPermission$1, getAppSandboxConfig: getAppSandboxConfig$1 } = await import("./permissions-D7-M2lRi.mjs");
2459
- const { launchSandbox: launchSandbox$1 } = await import("./launcher-DD6vpEFb.mjs");
2460
- const { buildSandboxConfig: buildSandboxConfig$1, formatPermissionsSummary: formatPermissionsSummary$1 } = await import("./config-builder-VSUaGlaV.mjs");
2461
- const { extractAppPermissions: extractAppPermissions$1 } = await import("./permissions-extractor-ySRyhQut.mjs");
2458
+ const { getAppIdentifier: getAppIdentifier$1, checkApiKeyPermission: checkApiKeyPermission$1, getAppSandboxConfig: getAppSandboxConfig$1 } = await import("./permissions-DOOzghc5.mjs");
2459
+ const { launchSandbox: launchSandbox$1 } = await import("./launcher-CSdy4_ZV.mjs");
2460
+ const { buildSandboxConfig: buildSandboxConfig$1, formatPermissionsSummary: formatPermissionsSummary$1 } = await import("./config-builder-CkkAqWMY.mjs");
2461
+ const { extractAppPermissions: extractAppPermissions$1 } = await import("./permissions-extractor-B3XI8JLv.mjs");
2462
2462
  const appId = getAppIdentifier$1();
2463
2463
  const declaredPermissions = await extractAppPermissions$1(absoluteEntryPath);
2464
2464
  if (declaredPermissions) {
@@ -2505,6 +2505,7 @@ async function executeApp(ref, repoPath, args$1, mcp) {
2505
2505
 
2506
2506
  //#endregion
2507
2507
  //#region src/bin-registry/commands.ts
2508
+ init_parser();
2508
2509
  async function installCommand(args$1) {
2509
2510
  const target = args$1[0];
2510
2511
  if (!target) throw new ExitError("Missing target\nUsage: kly install <file|user/repo[@ref]>\n or: kly install --setup-path");
@@ -2512,13 +2513,11 @@ async function installCommand(args$1) {
2512
2513
  await setupPath();
2513
2514
  return;
2514
2515
  }
2515
- if (isRemoteRef(target)) {
2516
- const { runRemote: runRemote$1 } = await import("./remote-tQeFZX9o.mjs");
2517
- await runRemote$1(target, {
2518
- args: args$1.slice(1),
2519
- skipRegister: false
2520
- });
2521
- } else {
2516
+ if (isRemoteRef(target)) await runRemote(target, {
2517
+ args: args$1.slice(1),
2518
+ skipRegister: false
2519
+ });
2520
+ else {
2522
2521
  const absolutePath = resolve(process.cwd(), target);
2523
2522
  const detection = detectBins(absolutePath);
2524
2523
  if (!detection.hasBin) {
@@ -2541,17 +2540,34 @@ async function uninstallCommand(args$1) {
2541
2540
  await unregisterCommand(commandName, { skipConfirm: false });
2542
2541
  }
2543
2542
  async function linkCommand(args$1) {
2544
- const targetPath = args$1[0] || process.cwd();
2545
- const absolutePath = resolve(process.cwd(), targetPath);
2546
- const detection = detectBins(absolutePath);
2547
- if (!detection.hasBin) throw new ExitError("No bin field found in package.json");
2548
- log.step(`Linking ${detection.projectName}...`);
2549
- await autoRegisterBins(absolutePath, {
2550
- type: "local",
2551
- force: true,
2552
- skipConfirm: true
2553
- });
2554
- log.success("Linked successfully!");
2543
+ const target = args$1[0] || process.cwd();
2544
+ if (isRemoteRef(target)) {
2545
+ const ref = parseRemoteRef(target);
2546
+ if (!ref) throw new ExitError(`Invalid remote reference: ${target}`);
2547
+ const repoPath = getRepoCachePath(ref);
2548
+ if (!checkCache(ref).valid) throw new ExitError(`Remote package not cached. Run 'kly run ${target}' first to download it.`);
2549
+ const detection = detectBins(repoPath);
2550
+ if (!detection.hasBin) throw new ExitError("No bin field found in package.json");
2551
+ log.step(`Linking ${detection.projectName}...`);
2552
+ await autoRegisterBins(repoPath, {
2553
+ type: "remote",
2554
+ remoteRef: target,
2555
+ force: true,
2556
+ skipConfirm: true
2557
+ });
2558
+ log.success("Linked successfully!");
2559
+ } else {
2560
+ const absolutePath = resolve(process.cwd(), target);
2561
+ const detection = detectBins(absolutePath);
2562
+ if (!detection.hasBin) throw new ExitError("No bin field found in package.json");
2563
+ log.step(`Linking ${detection.projectName}...`);
2564
+ await autoRegisterBins(absolutePath, {
2565
+ type: "local",
2566
+ force: true,
2567
+ skipConfirm: true
2568
+ });
2569
+ log.success("Linked successfully!");
2570
+ }
2555
2571
  }
2556
2572
  async function listCommand() {
2557
2573
  const commands = listCommands();
@@ -3382,7 +3398,8 @@ function buildSandboxConfig(permissions) {
3382
3398
  const userSandbox = permissions.sandbox;
3383
3399
  if (userSandbox.network?.allowedDomains) {
3384
3400
  const domains = userSandbox.network.allowedDomains.filter((d) => d !== void 0);
3385
- allowedDomains = [...allowedDomains, ...domains];
3401
+ if (domains.includes("*")) allowedDomains = void 0;
3402
+ else allowedDomains = [...allowedDomains ?? [], ...domains];
3386
3403
  }
3387
3404
  if (userSandbox.filesystem) {
3388
3405
  if (userSandbox.filesystem.allowWrite) allowWrite = userSandbox.filesystem.allowWrite.map(resolveFilesystemPath).filter((p$1) => p$1 !== void 0);
@@ -3393,7 +3410,7 @@ function buildSandboxConfig(permissions) {
3393
3410
  }
3394
3411
  }
3395
3412
  return {
3396
- network: {
3413
+ network: allowedDomains === void 0 ? { deniedDomains: [] } : {
3397
3414
  allowedDomains,
3398
3415
  deniedDomains: []
3399
3416
  },
@@ -3414,10 +3431,11 @@ function formatPermissionsSummary(permissions) {
3414
3431
  if (permissions?.apiKeys) summary.push("• API Keys access (to call LLM APIs)");
3415
3432
  const config = buildSandboxConfig(permissions);
3416
3433
  const currentDir = process.cwd();
3417
- if (config.network.allowedDomains.length > 0) if (config.network.allowedDomains.includes("*")) summary.push("• Network: All domains");
3418
- else {
3419
- const domains = config.network.allowedDomains.slice(0, 3).join(", ");
3420
- const more = config.network.allowedDomains.length > 3 ? ` +${config.network.allowedDomains.length - 3} more` : "";
3434
+ const allowedDomains = config.network.allowedDomains;
3435
+ if (allowedDomains === void 0) summary.push("• Network: All domains (unrestricted)");
3436
+ else if (allowedDomains.length > 0) {
3437
+ const domains = allowedDomains.slice(0, 3).join(", ");
3438
+ const more = allowedDomains.length > 3 ? ` +${allowedDomains.length - 3} more` : "";
3421
3439
  summary.push(`• Network: ${domains}${more}`);
3422
3440
  }
3423
3441
  if (config.filesystem.allowWrite.length > 1 || config.filesystem.allowWrite.length === 1 && config.filesystem.allowWrite[0] !== currentDir) {
@@ -3467,7 +3485,8 @@ async function extractAppPermissions(scriptPath) {
3467
3485
  */
3468
3486
  function needsPermissionPrompt(permissions, sandboxConfig) {
3469
3487
  if (permissions?.apiKeys) return true;
3470
- if (sandboxConfig.network.allowedDomains.length > 0) return true;
3488
+ const allowedDomains = sandboxConfig.network.allowedDomains;
3489
+ if (allowedDomains === void 0 || allowedDomains.length > 0) return true;
3471
3490
  if (permissions?.sandbox?.filesystem) return true;
3472
3491
  return false;
3473
3492
  }
@@ -3542,7 +3561,7 @@ function checkStoredPermission(appId) {
3542
3561
  const args = process.argv.slice(2);
3543
3562
  const command = args[0];
3544
3563
  async function main() {
3545
- intro(`${colors.bgHex("#dc7702")(colors.black(` Kly ${colors.italic("0.3.0")} `))}`);
3564
+ intro(`${colors.bgHex("#dc7702")(colors.black(` Kly ${colors.italic("0.3.1")} `))}`);
3546
3565
  if (!command || command === "--help" || command === "-h") {
3547
3566
  showHelp();
3548
3567
  return;
@@ -3714,7 +3733,7 @@ Examples:
3714
3733
  kly install --setup-path`);
3715
3734
  }
3716
3735
  function showVersion() {
3717
- log.message("0.3.0");
3736
+ log.message("0.3.1");
3718
3737
  }
3719
3738
  main().then(() => {
3720
3739
  outro(`ヾ( ̄▽ ̄)Bye~`);
@@ -3731,5 +3750,5 @@ main().then(() => {
3731
3750
  });
3732
3751
 
3733
3752
  //#endregion
3734
- export { getRegistryPath as A, unregisterCommand as C, removeShim as D, getShimDir as E, detectBins as F, isCommandAvailable as I, log as L, readRegistry as M, removeCommand as N, addCommand as O, writeRegistry as P, shouldReregisterLocal as S, generateShimPath as T, checkPathSetup as _, getAppIdentifier as a, setupPath as b, listPermissions as c, savePermissions as d, launchSandbox as f, parseRemoteRef as g, isRemoteRef as h, clearAllPermissions as i, listCommands as j, getCommand as k, loadPermissions as l, invalidateCache as m, formatPermissionsSummary as n, getAppName as o, runRemote as p, checkApiKeyPermission as r, getAppSandboxConfig as s, buildSandboxConfig as t, revokePermission as u, getShellConfigFile as v, createShim as w, autoRegisterBins as x, isKlyBinInPath as y };
3753
+ export { writeRegistry as A, removeShim as C, listCommands as D, getRegistryPath as E, isCommandAvailable as M, log as N, readRegistry as O, getShimDir as S, getCommand as T, autoRegisterBins as _, getAppIdentifier as a, createShim as b, listPermissions as c, savePermissions as d, launchSandbox as f, setupPath as g, isKlyBinInPath as h, clearAllPermissions as i, detectBins as j, removeCommand as k, loadPermissions as l, getShellConfigFile as m, formatPermissionsSummary as n, getAppName as o, checkPathSetup as p, checkApiKeyPermission as r, getAppSandboxConfig as s, buildSandboxConfig as t, revokePermission as u, shouldReregisterLocal as v, addCommand as w, generateShimPath as x, unregisterCommand as y };
3735
3754
  //# sourceMappingURL=kly.mjs.map