kly 0.1.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/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/ai/context.mjs +79 -0
- package/dist/ai/context.mjs.map +1 -0
- package/dist/ai/storage.mjs +50 -0
- package/dist/ai/storage.mjs.map +1 -0
- package/dist/bin/kly.d.mts +1 -0
- package/dist/bin/kly.mjs +2888 -0
- package/dist/bin/kly.mjs.map +1 -0
- package/dist/bin/launcher-vTpgdO9n.mjs +3 -0
- package/dist/bin/permissions-2r_7ZqaH.mjs +3 -0
- package/dist/cli.mjs +229 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/define-app.d.mts +33 -0
- package/dist/define-app.d.mts.map +1 -0
- package/dist/define-app.mjs +183 -0
- package/dist/define-app.mjs.map +1 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.mjs +15 -0
- package/dist/mcp/index.mjs +4 -0
- package/dist/mcp/schema-converter.d.mts +13 -0
- package/dist/mcp/schema-converter.d.mts.map +1 -0
- package/dist/mcp/schema-converter.mjs +30 -0
- package/dist/mcp/schema-converter.mjs.map +1 -0
- package/dist/mcp/server.d.mts +33 -0
- package/dist/mcp/server.d.mts.map +1 -0
- package/dist/mcp/server.mjs +92 -0
- package/dist/mcp/server.mjs.map +1 -0
- package/dist/permissions/index.mjs +123 -0
- package/dist/permissions/index.mjs.map +1 -0
- package/dist/sandbox/bundled-executor.d.mts +17 -0
- package/dist/sandbox/bundled-executor.d.mts.map +1 -0
- package/dist/sandbox/bundled-executor.mjs +175 -0
- package/dist/sandbox/bundled-executor.mjs.map +1 -0
- package/dist/sandbox/ipc-client.mjs +40 -0
- package/dist/sandbox/ipc-client.mjs.map +1 -0
- package/dist/sandbox/sandboxed-context.mjs +14 -0
- package/dist/sandbox/sandboxed-context.mjs.map +1 -0
- package/dist/shared/constants.mjs +36 -0
- package/dist/shared/constants.mjs.map +1 -0
- package/dist/shared/runtime-mode.mjs +59 -0
- package/dist/shared/runtime-mode.mjs.map +1 -0
- package/dist/tool.d.mts +42 -0
- package/dist/tool.d.mts.map +1 -0
- package/dist/tool.mjs +38 -0
- package/dist/tool.mjs.map +1 -0
- package/dist/types.d.mts +282 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +19 -0
- package/dist/types.mjs.map +1 -0
- package/dist/ui/components/confirm.d.mts +13 -0
- package/dist/ui/components/confirm.d.mts.map +1 -0
- package/dist/ui/components/confirm.mjs +37 -0
- package/dist/ui/components/confirm.mjs.map +1 -0
- package/dist/ui/components/form.d.mts +50 -0
- package/dist/ui/components/form.d.mts.map +1 -0
- package/dist/ui/components/form.mjs +92 -0
- package/dist/ui/components/form.mjs.map +1 -0
- package/dist/ui/components/input.d.mts +29 -0
- package/dist/ui/components/input.d.mts.map +1 -0
- package/dist/ui/components/input.mjs +42 -0
- package/dist/ui/components/input.mjs.map +1 -0
- package/dist/ui/components/select.d.mts +41 -0
- package/dist/ui/components/select.d.mts.map +1 -0
- package/dist/ui/components/select.mjs +50 -0
- package/dist/ui/components/select.mjs.map +1 -0
- package/dist/ui/components/spinner.d.mts +28 -0
- package/dist/ui/components/spinner.d.mts.map +1 -0
- package/dist/ui/components/spinner.mjs +35 -0
- package/dist/ui/components/spinner.mjs.map +1 -0
- package/dist/ui/components/table.d.mts +60 -0
- package/dist/ui/components/table.d.mts.map +1 -0
- package/dist/ui/components/table.mjs +143 -0
- package/dist/ui/components/table.mjs.map +1 -0
- package/dist/ui/index.d.mts +9 -0
- package/dist/ui/utils/colors.d.mts +38 -0
- package/dist/ui/utils/colors.d.mts.map +1 -0
- package/dist/ui/utils/colors.mjs +64 -0
- package/dist/ui/utils/colors.mjs.map +1 -0
- package/dist/ui/utils/output.d.mts +23 -0
- package/dist/ui/utils/output.d.mts.map +1 -0
- package/dist/ui/utils/output.mjs +42 -0
- package/dist/ui/utils/output.mjs.map +1 -0
- package/dist/ui/utils/tty.d.mts +9 -0
- package/dist/ui/utils/tty.d.mts.map +1 -0
- package/dist/ui/utils/tty.mjs +12 -0
- package/dist/ui/utils/tty.mjs.map +1 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 xinyao27 <https://github.com/xinyao27>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { checkApiKeyPermission, getAppIdentifier } from "../permissions/index.mjs";
|
|
2
|
+
import { getCurrentModelConfig, listModels } from "./storage.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/ai/context.ts
|
|
5
|
+
/**
|
|
6
|
+
* Create models context for ExecuteContext
|
|
7
|
+
* Provides access to configured LLM models and their credentials (with permission checks)
|
|
8
|
+
*/
|
|
9
|
+
function createModelsContext() {
|
|
10
|
+
let permissionChecked = false;
|
|
11
|
+
let permissionGranted = false;
|
|
12
|
+
/**
|
|
13
|
+
* Check permission before allowing access to API keys
|
|
14
|
+
*/
|
|
15
|
+
async function ensurePermission() {
|
|
16
|
+
if (permissionChecked) {
|
|
17
|
+
if (!permissionGranted) throw new Error("Permission denied: This app does not have permission to access API keys.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
permissionGranted = await checkApiKeyPermission(getAppIdentifier());
|
|
21
|
+
permissionChecked = true;
|
|
22
|
+
if (!permissionGranted) throw new Error("Permission denied: This app does not have permission to access API keys.");
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
list() {
|
|
26
|
+
return listModels().map((m) => ({
|
|
27
|
+
name: m.name,
|
|
28
|
+
provider: m.config.provider,
|
|
29
|
+
model: m.config.model,
|
|
30
|
+
isCurrent: m.isCurrent
|
|
31
|
+
}));
|
|
32
|
+
},
|
|
33
|
+
getCurrent() {
|
|
34
|
+
const current = listModels().find((m) => m.isCurrent);
|
|
35
|
+
if (!current) return null;
|
|
36
|
+
return {
|
|
37
|
+
name: current.name,
|
|
38
|
+
provider: current.config.provider,
|
|
39
|
+
model: current.config.model,
|
|
40
|
+
isCurrent: true
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
get(name) {
|
|
44
|
+
const found = listModels().find((m) => m.name === name);
|
|
45
|
+
if (!found) return null;
|
|
46
|
+
return {
|
|
47
|
+
name: found.name,
|
|
48
|
+
provider: found.config.provider,
|
|
49
|
+
model: found.config.model,
|
|
50
|
+
isCurrent: found.isCurrent
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
async getConfigAsync(name) {
|
|
54
|
+
await ensurePermission();
|
|
55
|
+
if (name) {
|
|
56
|
+
const found = listModels().find((m) => m.name === name);
|
|
57
|
+
if (!found) return null;
|
|
58
|
+
return {
|
|
59
|
+
provider: found.config.provider,
|
|
60
|
+
model: found.config.model,
|
|
61
|
+
apiKey: found.config.apiKey,
|
|
62
|
+
baseURL: found.config.baseURL
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const current = getCurrentModelConfig();
|
|
66
|
+
if (!current) return null;
|
|
67
|
+
return {
|
|
68
|
+
provider: current.provider,
|
|
69
|
+
model: current.model,
|
|
70
|
+
apiKey: current.apiKey,
|
|
71
|
+
baseURL: current.baseURL
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//#endregion
|
|
78
|
+
export { createModelsContext };
|
|
79
|
+
//# sourceMappingURL=context.mjs.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
//#region src/ai/storage.ts
|
|
6
|
+
const CONFIG_DIR = join(homedir(), ".kly");
|
|
7
|
+
const CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
8
|
+
/**
|
|
9
|
+
* Ensure config directory exists
|
|
10
|
+
*/
|
|
11
|
+
function ensureConfigDir() {
|
|
12
|
+
if (!existsSync(CONFIG_DIR)) mkdirSync(CONFIG_DIR, { recursive: true });
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Load configuration from ~/.kly/config.json
|
|
16
|
+
*/
|
|
17
|
+
function loadConfig() {
|
|
18
|
+
ensureConfigDir();
|
|
19
|
+
if (!existsSync(CONFIG_FILE)) return { models: {} };
|
|
20
|
+
try {
|
|
21
|
+
const content = readFileSync(CONFIG_FILE, "utf-8");
|
|
22
|
+
return JSON.parse(content);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error("Failed to parse config file:", error);
|
|
25
|
+
return { models: {} };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get current active model configuration
|
|
30
|
+
*/
|
|
31
|
+
function getCurrentModelConfig() {
|
|
32
|
+
const config = loadConfig();
|
|
33
|
+
if (!config.currentModel) return null;
|
|
34
|
+
return config.models[config.currentModel] || null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* List all configured models
|
|
38
|
+
*/
|
|
39
|
+
function listModels() {
|
|
40
|
+
const config = loadConfig();
|
|
41
|
+
return Object.entries(config.models).map(([name, modelConfig]) => ({
|
|
42
|
+
name,
|
|
43
|
+
config: modelConfig,
|
|
44
|
+
isCurrent: name === config.currentModel
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//#endregion
|
|
49
|
+
export { getCurrentModelConfig, listModels };
|
|
50
|
+
//# sourceMappingURL=storage.mjs.map
|
|
@@ -0,0 +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 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 (error) {\n console.error(\"Failed to parse config file:\", error);\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":";;;;;AAKA,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,OAAO;AACd,UAAQ,MAAM,gCAAgC,MAAM;AACpD,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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|