kly 0.2.0 → 0.3.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.
Potentially problematic release.
This version of kly might be problematic. Click here for more details.
- package/dist/ai/storage.mjs +3 -2
- package/dist/ai/storage.mjs.map +1 -1
- package/dist/bin/bin-registry-DOBspniG.mjs +3 -0
- package/dist/bin/kly.mjs +3217 -2430
- package/dist/bin/kly.mjs.map +1 -1
- package/dist/bin/{permissions-extractor-BfUPS0Tr.mjs → permissions-extractor-ySRyhQut.mjs} +4 -2
- package/dist/bin/permissions-extractor-ySRyhQut.mjs.map +1 -0
- package/dist/bin/remote-tQeFZX9o.mjs +3 -0
- package/dist/cli.mjs +4 -4
- package/dist/cli.mjs.map +1 -1
- package/dist/define-app.d.mts.map +1 -1
- package/dist/define-app.mjs +35 -28
- package/dist/define-app.mjs.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +3 -3
- package/dist/mcp/schema-converter.d.mts.map +1 -1
- package/dist/mcp/schema-converter.mjs +2 -1
- package/dist/mcp/schema-converter.mjs.map +1 -1
- package/dist/mcp/server.d.mts.map +1 -1
- package/dist/mcp/server.mjs +7 -6
- package/dist/mcp/server.mjs.map +1 -1
- package/dist/permissions/index.mjs +8 -10
- package/dist/permissions/index.mjs.map +1 -1
- package/dist/sandbox/bundled-executor.d.mts.map +1 -1
- package/dist/sandbox/bundled-executor.mjs +67 -10
- package/dist/sandbox/bundled-executor.mjs.map +1 -1
- package/dist/sandbox/ipc-client.mjs +2 -0
- package/dist/sandbox/ipc-client.mjs.map +1 -1
- package/dist/shared/constants.mjs +5 -1
- package/dist/shared/constants.mjs.map +1 -1
- package/dist/shared/errors.mjs +21 -0
- package/dist/shared/errors.mjs.map +1 -0
- package/dist/types.d.mts +7 -6
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/ui/components/confirm.d.mts.map +1 -1
- package/dist/ui/components/confirm.mjs +4 -8
- package/dist/ui/components/confirm.mjs.map +1 -1
- package/dist/ui/components/form.d.mts.map +1 -1
- package/dist/ui/components/form.mjs +12 -26
- package/dist/ui/components/form.mjs.map +1 -1
- package/dist/ui/components/input.d.mts.map +1 -1
- package/dist/ui/components/input.mjs +3 -7
- package/dist/ui/components/input.mjs.map +1 -1
- package/dist/ui/{utils/output.d.mts → components/log.d.mts} +22 -2
- package/dist/ui/components/log.d.mts.map +1 -0
- package/dist/ui/components/log.mjs +92 -0
- package/dist/ui/components/log.mjs.map +1 -0
- package/dist/ui/components/prompts.d.mts +1 -0
- package/dist/ui/components/select.d.mts.map +1 -1
- package/dist/ui/components/select.mjs +5 -8
- package/dist/ui/components/select.mjs.map +1 -1
- package/dist/ui/components/table.d.mts +1 -1
- package/dist/ui/components/table.d.mts.map +1 -1
- package/dist/ui/components/table.mjs +19 -19
- package/dist/ui/components/table.mjs.map +1 -1
- package/dist/ui/index.d.mts +3 -2
- package/dist/ui/utils/cancel.mjs +17 -0
- package/dist/ui/utils/cancel.mjs.map +1 -0
- package/dist/ui/utils/colors.d.mts +3 -3
- package/dist/ui/utils/colors.d.mts.map +1 -1
- package/dist/ui/utils/colors.mjs +21 -33
- package/dist/ui/utils/colors.mjs.map +1 -1
- package/package.json +14 -12
- package/dist/bin/permissions-extractor-BfUPS0Tr.mjs.map +0 -1
- package/dist/ui/utils/output.d.mts.map +0 -1
- package/dist/ui/utils/output.mjs +0 -42
- package/dist/ui/utils/output.mjs.map +0 -1
- /package/dist/bin/{config-builder-D5EtwOB3.mjs → config-builder-VSUaGlaV.mjs} +0 -0
- /package/dist/bin/{launcher-Ex3ynZdE.mjs → launcher-DD6vpEFb.mjs} +0 -0
- /package/dist/bin/{permissions-C_WgoA3t.mjs → permissions-D7-M2lRi.mjs} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.mjs","names":[],"sources":["../../../src/ui/components/input.ts"],"sourcesContent":["import * as p from \"@clack/prompts\";\nimport { sendIPCRequest } from \"../../sandbox/ipc-client\";\nimport { isMCP, isSandbox } from \"../../shared/runtime-mode\";\nimport { isTTY } from \"../utils/tty\";\n\n/**\n * Configuration for input component\n */\nexport interface InputConfig {\n /** Prompt message */\n prompt: string;\n /** Default value */\n defaultValue?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Maximum input length */\n maxLength?: number;\n}\n\n/**\n * Prompt for text input\n *\n * @example\n * ```typescript\n * const name = await input({\n * prompt: \"What's your name?\",\n * defaultValue: \"Anonymous\"\n * });\n * ```\n */\nexport async function input(config: InputConfig): Promise<string> {\n // Sandbox mode: use IPC to request input from host\n if (isSandbox()) {\n return sendIPCRequest<string>(\"prompt:input\", config);\n }\n\n // Non-TTY fallback: return default or throw\n if (!isTTY()) {\n if (config.defaultValue !== undefined) {\n return config.defaultValue;\n }\n\n // Provide MCP-specific error message\n if (isMCP()) {\n throw new Error(\n `Interactive input not available in MCP mode. All parameters must be defined in the tool's inputSchema. Missing parameter: ${config.prompt}`,\n );\n }\n\n throw new Error(\n \"Interactive input not available in non-TTY mode. Please provide all required arguments.\",\n );\n }\n\n const result = await p.text({\n message: config.prompt,\n defaultValue: config.defaultValue,\n placeholder: config.placeholder,\n validate: config.maxLength\n ? (value) => {\n if (value && value.length > config.maxLength!) {\n return `Input must be ${config.maxLength} characters or less`;\n }\n return undefined;\n }\n : undefined,\n });\n\n
|
|
1
|
+
{"version":3,"file":"input.mjs","names":[],"sources":["../../../src/ui/components/input.ts"],"sourcesContent":["import * as p from \"@clack/prompts\";\nimport { sendIPCRequest } from \"../../sandbox/ipc-client\";\nimport { isMCP, isSandbox } from \"../../shared/runtime-mode\";\nimport { handleCancel } from \"../utils/cancel\";\nimport { isTTY } from \"../utils/tty\";\n\n/**\n * Configuration for input component\n */\nexport interface InputConfig {\n /** Prompt message */\n prompt: string;\n /** Default value */\n defaultValue?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Maximum input length */\n maxLength?: number;\n}\n\n/**\n * Prompt for text input\n *\n * @example\n * ```typescript\n * const name = await input({\n * prompt: \"What's your name?\",\n * defaultValue: \"Anonymous\"\n * });\n * ```\n */\nexport async function input(config: InputConfig): Promise<string> {\n // Sandbox mode: use IPC to request input from host\n if (isSandbox()) {\n return sendIPCRequest<string>(\"prompt:input\", config);\n }\n\n // Non-TTY fallback: return default or throw\n if (!isTTY()) {\n if (config.defaultValue !== undefined) {\n return config.defaultValue;\n }\n\n // Provide MCP-specific error message\n if (isMCP()) {\n throw new Error(\n `Interactive input not available in MCP mode. All parameters must be defined in the tool's inputSchema. Missing parameter: ${config.prompt}`,\n );\n }\n\n throw new Error(\n \"Interactive input not available in non-TTY mode. Please provide all required arguments.\",\n );\n }\n\n const result = await p.text({\n message: config.prompt,\n defaultValue: config.defaultValue,\n placeholder: config.placeholder,\n validate: config.maxLength\n ? (value) => {\n if (value && value.length > config.maxLength!) {\n return `Input must be ${config.maxLength} characters or less`;\n }\n return undefined;\n }\n : undefined,\n });\n\n return handleCancel(result);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA+BA,eAAsB,MAAM,QAAsC;AAEhE,KAAI,WAAW,CACb,QAAO,eAAuB,gBAAgB,OAAO;AAIvD,KAAI,CAAC,OAAO,EAAE;AACZ,MAAI,OAAO,iBAAiB,OAC1B,QAAO,OAAO;AAIhB,MAAI,OAAO,CACT,OAAM,IAAI,MACR,6HAA6H,OAAO,SACrI;AAGH,QAAM,IAAI,MACR,0FACD;;AAiBH,QAAO,aAdQ,MAAM,EAAE,KAAK;EAC1B,SAAS,OAAO;EAChB,cAAc,OAAO;EACrB,aAAa,OAAO;EACpB,UAAU,OAAO,aACZ,UAAU;AACT,OAAI,SAAS,MAAM,SAAS,OAAO,UACjC,QAAO,iBAAiB,OAAO,UAAU;MAI7C;EACL,CAAC,CAEyB"}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
//#region src/ui/
|
|
1
|
+
//#region src/ui/components/log.d.ts
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
4
|
* Output a result to the console
|
|
4
5
|
*
|
|
5
6
|
* @param result - The result to display (string, object, etc.)
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* output("Hello, world!");
|
|
11
|
+
* output({ name: "John", age: 30 });
|
|
12
|
+
* ```
|
|
6
13
|
*/
|
|
7
14
|
declare function output(result: unknown): void;
|
|
8
15
|
/**
|
|
@@ -10,14 +17,27 @@ declare function output(result: unknown): void;
|
|
|
10
17
|
*
|
|
11
18
|
* @param message - Error message
|
|
12
19
|
* @param suggestions - Optional suggestions for fixing the error
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* error("Failed to load config", [
|
|
24
|
+
* "Check if config.json exists",
|
|
25
|
+
* "Verify JSON syntax"
|
|
26
|
+
* ]);
|
|
27
|
+
* ```
|
|
13
28
|
*/
|
|
14
29
|
declare function error(message: string, suggestions?: string[]): void;
|
|
15
30
|
/**
|
|
16
31
|
* Display help text
|
|
17
32
|
*
|
|
18
33
|
* @param content - Help text content
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* help("Usage: myapp <command> [options]");
|
|
38
|
+
* ```
|
|
19
39
|
*/
|
|
20
40
|
declare function help(content: string): void;
|
|
21
41
|
//#endregion
|
|
22
42
|
export { error, help, output };
|
|
23
|
-
//# sourceMappingURL=
|
|
43
|
+
//# sourceMappingURL=log.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.d.mts","names":[],"sources":["../../../src/ui/components/log.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;iBAiFgB,MAAA;;;;;;;;;;;;;;;iBA0BA,KAAA;;;;;;;;;;;iBAsBA,IAAA"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { colors } from "../utils/colors.mjs";
|
|
2
|
+
import * as p from "@clack/prompts";
|
|
3
|
+
|
|
4
|
+
//#region src/ui/components/log.ts
|
|
5
|
+
/**
|
|
6
|
+
* Log utilities for consistent CLI output
|
|
7
|
+
*
|
|
8
|
+
* Uses @clack/prompts log functions for styled output
|
|
9
|
+
*/
|
|
10
|
+
const log = {
|
|
11
|
+
info(message) {
|
|
12
|
+
p.log.info(message);
|
|
13
|
+
},
|
|
14
|
+
success(message) {
|
|
15
|
+
p.log.success(message);
|
|
16
|
+
},
|
|
17
|
+
step(message) {
|
|
18
|
+
p.log.step(message);
|
|
19
|
+
},
|
|
20
|
+
warn(message) {
|
|
21
|
+
p.log.warn(message);
|
|
22
|
+
},
|
|
23
|
+
message(message) {
|
|
24
|
+
p.log.message(message);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Output a result to the console
|
|
29
|
+
*
|
|
30
|
+
* @param result - The result to display (string, object, etc.)
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* output("Hello, world!");
|
|
35
|
+
* output({ name: "John", age: 30 });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
function output(result) {
|
|
39
|
+
if (result === void 0 || result === null) return;
|
|
40
|
+
if (typeof result === "string") p.log.message(result);
|
|
41
|
+
else p.log.message(JSON.stringify(result, null, 2));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Display an error message with optional suggestions
|
|
45
|
+
*
|
|
46
|
+
* @param message - Error message
|
|
47
|
+
* @param suggestions - Optional suggestions for fixing the error
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* error("Failed to load config", [
|
|
52
|
+
* "Check if config.json exists",
|
|
53
|
+
* "Verify JSON syntax"
|
|
54
|
+
* ]);
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
function error(message, suggestions) {
|
|
58
|
+
p.log.error(message);
|
|
59
|
+
if (suggestions?.length) {
|
|
60
|
+
p.log.message("");
|
|
61
|
+
p.log.message(colors.dim("Suggestions:"));
|
|
62
|
+
for (const suggestion of suggestions) p.log.message(` ${colors.dim("•")} ${suggestion}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Display help text
|
|
67
|
+
*
|
|
68
|
+
* @param content - Help text content
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* help("Usage: myapp <command> [options]");
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
function help(content) {
|
|
76
|
+
p.log.message(content);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Display a cancellation message and optionally exit
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* cancel("Operation cancelled");
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
function cancel(message) {
|
|
87
|
+
p.cancel(message);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
//#endregion
|
|
91
|
+
export { cancel, error, help, log, output };
|
|
92
|
+
//# sourceMappingURL=log.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.mjs","names":[],"sources":["../../../src/ui/components/log.ts"],"sourcesContent":["import * as p from \"@clack/prompts\";\nimport { colors } from \"../utils/colors\";\n\n/**\n * Log utilities for consistent CLI output\n *\n * Uses @clack/prompts log functions for styled output\n */\nexport const log = {\n /**\n * Display an info message\n *\n * @example\n * ```typescript\n * log.info(\"Processing files...\");\n * ```\n */\n info(message: string): void {\n p.log.info(message);\n },\n\n /**\n * Display a success message\n *\n * @example\n * ```typescript\n * log.success(\"Build completed successfully!\");\n * ```\n */\n success(message: string): void {\n p.log.success(message);\n },\n\n /**\n * Display a step message\n *\n * @example\n * ```typescript\n * log.step(\"Installing dependencies\");\n * ```\n */\n step(message: string): void {\n p.log.step(message);\n },\n\n /**\n * Display a warning message\n *\n * @example\n * ```typescript\n * log.warn(\"Config file not found, using defaults\");\n * ```\n */\n warn(message: string): void {\n p.log.warn(message);\n },\n\n /**\n * Display a general message\n *\n * @example\n * ```typescript\n * log.message(\"Welcome to the CLI!\");\n * ```\n */\n message(message: string): void {\n p.log.message(message);\n },\n};\n\n/**\n * Output a result to the console\n *\n * @param result - The result to display (string, object, etc.)\n *\n * @example\n * ```typescript\n * output(\"Hello, world!\");\n * output({ name: \"John\", age: 30 });\n * ```\n */\nexport function output(result: unknown): void {\n if (result === undefined || result === null) {\n return;\n }\n\n if (typeof result === \"string\") {\n p.log.message(result);\n } else {\n p.log.message(JSON.stringify(result, null, 2));\n }\n}\n\n/**\n * Display an error message with optional suggestions\n *\n * @param message - Error message\n * @param suggestions - Optional suggestions for fixing the error\n *\n * @example\n * ```typescript\n * error(\"Failed to load config\", [\n * \"Check if config.json exists\",\n * \"Verify JSON syntax\"\n * ]);\n * ```\n */\nexport function error(message: string, suggestions?: string[]): void {\n p.log.error(message);\n\n if (suggestions?.length) {\n p.log.message(\"\");\n p.log.message(colors.dim(\"Suggestions:\"));\n for (const suggestion of suggestions) {\n p.log.message(` ${colors.dim(\"•\")} ${suggestion}`);\n }\n }\n}\n\n/**\n * Display help text\n *\n * @param content - Help text content\n *\n * @example\n * ```typescript\n * help(\"Usage: myapp <command> [options]\");\n * ```\n */\nexport function help(content: string): void {\n p.log.message(content);\n}\n\n/**\n * Display an intro message at the start of your CLI\n *\n * @example\n * ```typescript\n * intro(\"Welcome to my-cli v1.0.0\");\n * ```\n */\nexport function intro(message?: string): void {\n p.intro(message);\n}\n\n/**\n * Display an outro message at the end of your CLI\n *\n * @example\n * ```typescript\n * outro(\"Thanks for using my-cli!\");\n * ```\n */\nexport function outro(message?: string): void {\n p.outro(message);\n}\n\n/**\n * Display a cancellation message and optionally exit\n *\n * @example\n * ```typescript\n * cancel(\"Operation cancelled\");\n * ```\n */\nexport function cancel(message?: string): void {\n p.cancel(message);\n}\n\n/**\n * Check if a value is a cancel symbol\n *\n * @example\n * ```typescript\n * const result = await text({ message: \"Enter name\" });\n * if (isCancel(result)) {\n * cancel(\"Cancelled\");\n * process.exit(0);\n * }\n * ```\n */\nexport function isCancel(value: unknown): value is symbol {\n return p.isCancel(value);\n}\n\n/**\n * Add a note/box with styled content\n *\n * @example\n * ```typescript\n * note(\"npm install my-package\", \"Next steps\");\n * ```\n */\nexport function note(message: string, title?: string): void {\n p.note(message, title);\n}\n"],"mappings":";;;;;;;;;AAQA,MAAa,MAAM;CASjB,KAAK,SAAuB;AAC1B,IAAE,IAAI,KAAK,QAAQ;;CAWrB,QAAQ,SAAuB;AAC7B,IAAE,IAAI,QAAQ,QAAQ;;CAWxB,KAAK,SAAuB;AAC1B,IAAE,IAAI,KAAK,QAAQ;;CAWrB,KAAK,SAAuB;AAC1B,IAAE,IAAI,KAAK,QAAQ;;CAWrB,QAAQ,SAAuB;AAC7B,IAAE,IAAI,QAAQ,QAAQ;;CAEzB;;;;;;;;;;;;AAaD,SAAgB,OAAO,QAAuB;AAC5C,KAAI,WAAW,UAAa,WAAW,KACrC;AAGF,KAAI,OAAO,WAAW,SACpB,GAAE,IAAI,QAAQ,OAAO;KAErB,GAAE,IAAI,QAAQ,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;;;;;;;;;;;;;;;;AAkBlD,SAAgB,MAAM,SAAiB,aAA8B;AACnE,GAAE,IAAI,MAAM,QAAQ;AAEpB,KAAI,aAAa,QAAQ;AACvB,IAAE,IAAI,QAAQ,GAAG;AACjB,IAAE,IAAI,QAAQ,OAAO,IAAI,eAAe,CAAC;AACzC,OAAK,MAAM,cAAc,YACvB,GAAE,IAAI,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC,GAAG,aAAa;;;;;;;;;;;;;AAezD,SAAgB,KAAK,SAAuB;AAC1C,GAAE,IAAI,QAAQ,QAAQ;;;;;;;;;;AAmCxB,SAAgB,OAAO,SAAwB;AAC7C,GAAE,OAAO,QAAQ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "@clack/prompts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.d.mts","names":[],"sources":["../../../src/ui/components/select.ts"],"sourcesContent":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"select.d.mts","names":[],"sources":["../../../src/ui/components/select.ts"],"sourcesContent":[],"mappings":";;AASA;AAcA;AAqBsB,UAnCL,YAmCW,CAAA,IAAA,MAAA,CAAA,CAAA;EAAkC;EAAb,IAAA,EAAA,MAAA;EAA0B;EAAR,WAAA,CAAA,EAAA,MAAA;EAAO;SA7BjE;;;;;;;UAQQ;;WAEN,aAAa;;;;;;;;;;;;;;;;;;iBAmBF,2BAA2B,aAAa,KAAK,QAAQ"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isMCP, isSandbox } from "../../shared/runtime-mode.mjs";
|
|
2
|
+
import { handleCancel } from "../utils/cancel.mjs";
|
|
2
3
|
import { isTTY } from "../utils/tty.mjs";
|
|
3
4
|
import { sendIPCRequest } from "../../sandbox/ipc-client.mjs";
|
|
4
5
|
import * as p from "@clack/prompts";
|
|
@@ -32,17 +33,13 @@ async function select(config) {
|
|
|
32
33
|
const mappedOptions = config.options.map((opt) => ({
|
|
33
34
|
label: opt.name,
|
|
34
35
|
value: opt.value,
|
|
35
|
-
...opt.description && { hint: opt.description }
|
|
36
|
+
...opt.description && { hint: opt.description },
|
|
37
|
+
...opt.disabled !== void 0 && { disabled: opt.disabled }
|
|
36
38
|
}));
|
|
37
|
-
|
|
39
|
+
return handleCancel(await p.select({
|
|
38
40
|
message: config.prompt ?? "Select an option",
|
|
39
41
|
options: mappedOptions
|
|
40
|
-
});
|
|
41
|
-
if (p.isCancel(result)) {
|
|
42
|
-
p.cancel("Operation cancelled");
|
|
43
|
-
process.exit(0);
|
|
44
|
-
}
|
|
45
|
-
return result;
|
|
42
|
+
}));
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.mjs","names":[],"sources":["../../../src/ui/components/select.ts"],"sourcesContent":["import * as p from \"@clack/prompts\";\nimport { sendIPCRequest } from \"../../sandbox/ipc-client\";\nimport { isMCP, isSandbox } from \"../../shared/runtime-mode\";\nimport { isTTY } from \"../utils/tty\";\n\n/**\n * Option for select menus\n */\nexport interface SelectOption<T = string> {\n /** Display name */\n name: string;\n /** Optional description shown below name */\n description?: string;\n /** Value returned when selected */\n value: T;\n /** Disable this option */\n disabled?: boolean;\n}\n\n/**\n * Configuration for select component\n */\nexport interface SelectConfig<T> {\n /** Options to choose from */\n options: SelectOption<T>[];\n /** Prompt message */\n prompt?: string;\n}\n\n/**\n * Show a selection menu and wait for user choice\n *\n * @example\n * ```typescript\n * const color = await select({\n * options: [\n * { name: \"Red\", value: \"red\" },\n * { name: \"Blue\", value: \"blue\", description: \"Ocean color\" },\n * ],\n * prompt: \"Pick a color\"\n * });\n * ```\n */\nexport async function select<T = string>(config: SelectConfig<T>): Promise<T> {\n // Sandbox mode: use IPC to request select from host\n if (isSandbox()) {\n return sendIPCRequest<T>(\"prompt:select\", {\n prompt: config.prompt ?? \"Select an option\",\n options: config.options,\n });\n }\n\n // Non-TTY fallback: auto-select first option or throw in MCP mode\n if (!isTTY()) {\n // In MCP mode, interactive selection is not allowed\n if (isMCP()) {\n throw new Error(\n `Interactive selection not available in MCP mode. All parameters must be defined in the tool's inputSchema. Selection prompt: ${config.prompt}`,\n );\n }\n\n const firstOption = config.options[0];\n if (!firstOption) {\n throw new Error(\"No options provided\");\n }\n return firstOption.value;\n }\n\n // Map to @clack/prompts Option format\n // Using type assertion due to complex Option<T> conditional types\n const mappedOptions = config.options.map((opt) => ({\n label: opt.name,\n value: opt.value as unknown,\n ...(opt.description && { hint: opt.description }),\n }));\n\n const result = await p.select({\n message: config.prompt ?? \"Select an option\",\n options: mappedOptions,\n });\n\n
|
|
1
|
+
{"version":3,"file":"select.mjs","names":[],"sources":["../../../src/ui/components/select.ts"],"sourcesContent":["import * as p from \"@clack/prompts\";\nimport { sendIPCRequest } from \"../../sandbox/ipc-client\";\nimport { isMCP, isSandbox } from \"../../shared/runtime-mode\";\nimport { handleCancel } from \"../utils/cancel\";\nimport { isTTY } from \"../utils/tty\";\n\n/**\n * Option for select menus\n */\nexport interface SelectOption<T = string> {\n /** Display name */\n name: string;\n /** Optional description shown below name */\n description?: string;\n /** Value returned when selected */\n value: T;\n /** Disable this option */\n disabled?: boolean;\n}\n\n/**\n * Configuration for select component\n */\nexport interface SelectConfig<T> {\n /** Options to choose from */\n options: SelectOption<T>[];\n /** Prompt message */\n prompt?: string;\n}\n\n/**\n * Show a selection menu and wait for user choice\n *\n * @example\n * ```typescript\n * const color = await select({\n * options: [\n * { name: \"Red\", value: \"red\" },\n * { name: \"Blue\", value: \"blue\", description: \"Ocean color\" },\n * ],\n * prompt: \"Pick a color\"\n * });\n * ```\n */\nexport async function select<T = string>(config: SelectConfig<T>): Promise<T> {\n // Sandbox mode: use IPC to request select from host\n if (isSandbox()) {\n return sendIPCRequest<T>(\"prompt:select\", {\n prompt: config.prompt ?? \"Select an option\",\n options: config.options,\n });\n }\n\n // Non-TTY fallback: auto-select first option or throw in MCP mode\n if (!isTTY()) {\n // In MCP mode, interactive selection is not allowed\n if (isMCP()) {\n throw new Error(\n `Interactive selection not available in MCP mode. All parameters must be defined in the tool's inputSchema. Selection prompt: ${config.prompt}`,\n );\n }\n\n const firstOption = config.options[0];\n if (!firstOption) {\n throw new Error(\"No options provided\");\n }\n return firstOption.value;\n }\n\n // Map to @clack/prompts Option format\n // Using type assertion due to complex Option<T> conditional types\n const mappedOptions = config.options.map((opt) => ({\n label: opt.name,\n value: opt.value as unknown,\n ...(opt.description && { hint: opt.description }),\n ...(opt.disabled !== undefined && { disabled: opt.disabled }),\n }));\n\n const result = await p.select({\n message: config.prompt ?? \"Select an option\",\n options: mappedOptions,\n });\n\n return handleCancel(result) as T;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA4CA,eAAsB,OAAmB,QAAqC;AAE5E,KAAI,WAAW,CACb,QAAO,eAAkB,iBAAiB;EACxC,QAAQ,OAAO,UAAU;EACzB,SAAS,OAAO;EACjB,CAAC;AAIJ,KAAI,CAAC,OAAO,EAAE;AAEZ,MAAI,OAAO,CACT,OAAM,IAAI,MACR,gIAAgI,OAAO,SACxI;EAGH,MAAM,cAAc,OAAO,QAAQ;AACnC,MAAI,CAAC,YACH,OAAM,IAAI,MAAM,sBAAsB;AAExC,SAAO,YAAY;;CAKrB,MAAM,gBAAgB,OAAO,QAAQ,KAAK,SAAS;EACjD,OAAO,IAAI;EACX,OAAO,IAAI;EACX,GAAI,IAAI,eAAe,EAAE,MAAM,IAAI,aAAa;EAChD,GAAI,IAAI,aAAa,UAAa,EAAE,UAAU,IAAI,UAAU;EAC7D,EAAE;AAOH,QAAO,aALQ,MAAM,EAAE,OAAO;EAC5B,SAAS,OAAO,UAAU;EAC1B,SAAS;EACV,CAAC,CAEyB"}
|
|
@@ -44,7 +44,7 @@ interface TableConfig<T = Record<string, unknown>> {
|
|
|
44
44
|
* { key: "name", header: "Name" },
|
|
45
45
|
* { key: "age", header: "Age", align: "right" },
|
|
46
46
|
* { key: "status", header: "Status", formatter: (val) =>
|
|
47
|
-
* val === "active" ?
|
|
47
|
+
* val === "active" ? colors.green("✓ Active") : colors.red("✗ Inactive")
|
|
48
48
|
* },
|
|
49
49
|
* ],
|
|
50
50
|
* rows: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.d.mts","names":[],"sources":["../../../src/ui/components/table.ts"],"sourcesContent":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"table.d.mts","names":[],"sources":["../../../src/ui/components/table.ts"],"sourcesContent":[],"mappings":";;AAcA;AAKA;AAAiC,KALrB,WAAA,GAKqB,MAAA,GAAA,QAAA,GAAA,OAAA;;;;AAUI,UAVpB,WAUoB,CAAA,IAVJ,MAUI,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,CAAA;EAMpB;EAAgB,GAAA,EAAA,MAdpB,CAcoB;EAEV;EAAZ,MAAA,EAAA,MAAA;EAEH;EAAC,KAAA,CAAA,EAdC,WAcD;EAoMO;EAAU,KAAA,CAAA,EAAA,MAAA;EACJ;EAAZ,SAAA,CAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAAA,EA/M0B,CA+M1B,EAAA,GAAA,MAAA;;;;;UAzMO,gBAAgB;;WAEtB,YAAY;;QAEf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoMQ,UAAU,iCAChB,YAAY"}
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { isTTY } from "../utils/tty.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { colors } from "../utils/colors.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/ui/components/table.ts
|
|
5
5
|
/**
|
|
6
|
+
* Render table title lines
|
|
7
|
+
*/
|
|
8
|
+
function _renderTitle(title, styled) {
|
|
9
|
+
if (!title) return [];
|
|
10
|
+
return [
|
|
11
|
+
"",
|
|
12
|
+
styled ? colors.bold(title) : title,
|
|
13
|
+
""
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
6
17
|
* Align text within a given width
|
|
7
18
|
*/
|
|
8
19
|
function alignText(text, width, align) {
|
|
@@ -44,7 +55,7 @@ function calculateColumnWidths(columns, rows, showHeader) {
|
|
|
44
55
|
*/
|
|
45
56
|
function formatCell(value, row, column) {
|
|
46
57
|
if (column.formatter) return column.formatter(value, row);
|
|
47
|
-
if (value === null || value === void 0) return
|
|
58
|
+
if (value === null || value === void 0) return colors.dim("-");
|
|
48
59
|
return String(value);
|
|
49
60
|
}
|
|
50
61
|
/**
|
|
@@ -54,22 +65,15 @@ function renderTTY(config) {
|
|
|
54
65
|
const { columns, rows, showHeader = true, showBorders = true, title } = config;
|
|
55
66
|
const lines = [];
|
|
56
67
|
const widths = calculateColumnWidths(columns, rows, showHeader);
|
|
57
|
-
|
|
58
|
-
lines.push("");
|
|
59
|
-
lines.push(formatText(`${title}`, { bold: true }));
|
|
60
|
-
lines.push("");
|
|
61
|
-
}
|
|
68
|
+
lines.push(..._renderTitle(title, true));
|
|
62
69
|
if (showHeader) {
|
|
63
70
|
const headerCells = columns.map((col, i) => {
|
|
64
|
-
return alignText(
|
|
65
|
-
bold: true,
|
|
66
|
-
color: "cyan"
|
|
67
|
-
}), widths[i], col.align ?? "left");
|
|
71
|
+
return alignText(colors.cyan(colors.bold(col.header)), widths[i], col.align ?? "left");
|
|
68
72
|
});
|
|
69
73
|
lines.push(headerCells.join(" "));
|
|
70
74
|
if (showBorders) {
|
|
71
75
|
const separatorParts = widths.map((w) => "─".repeat(w));
|
|
72
|
-
lines.push(
|
|
76
|
+
lines.push(colors.gray(separatorParts.join("─")));
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
for (const row of rows) {
|
|
@@ -81,7 +85,7 @@ function renderTTY(config) {
|
|
|
81
85
|
}
|
|
82
86
|
if (showBorders && rows.length > 0) {
|
|
83
87
|
const separatorParts = widths.map((w) => "─".repeat(w));
|
|
84
|
-
lines.push(
|
|
88
|
+
lines.push(colors.gray(separatorParts.join("─")));
|
|
85
89
|
}
|
|
86
90
|
return lines.join("\n");
|
|
87
91
|
}
|
|
@@ -92,11 +96,7 @@ function renderPlain(config) {
|
|
|
92
96
|
const { columns, rows, showHeader = true, title } = config;
|
|
93
97
|
const lines = [];
|
|
94
98
|
const widths = calculateColumnWidths(columns, rows, showHeader);
|
|
95
|
-
|
|
96
|
-
lines.push("");
|
|
97
|
-
lines.push(title);
|
|
98
|
-
lines.push("");
|
|
99
|
-
}
|
|
99
|
+
lines.push(..._renderTitle(title, false));
|
|
100
100
|
if (showHeader) {
|
|
101
101
|
const headerCells = columns.map((col, i) => alignText(col.header, widths[i], col.align ?? "left"));
|
|
102
102
|
lines.push(headerCells.join(" "));
|
|
@@ -123,7 +123,7 @@ function renderPlain(config) {
|
|
|
123
123
|
* { key: "name", header: "Name" },
|
|
124
124
|
* { key: "age", header: "Age", align: "right" },
|
|
125
125
|
* { key: "status", header: "Status", formatter: (val) =>
|
|
126
|
-
* val === "active" ?
|
|
126
|
+
* val === "active" ? colors.green("✓ Active") : colors.red("✗ Inactive")
|
|
127
127
|
* },
|
|
128
128
|
* ],
|
|
129
129
|
* rows: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.mjs","names":["lines: string[]"],"sources":["../../../src/ui/components/table.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"table.mjs","names":["lines: string[]"],"sources":["../../../src/ui/components/table.ts"],"sourcesContent":["import { colors } from \"../utils/colors\";\nimport { isTTY } from \"../utils/tty\";\n\n/**\n * Render table title lines\n */\nfunction _renderTitle(title: string | undefined, styled: boolean): string[] {\n if (!title) return [];\n return [\"\", styled ? colors.bold(title) : title, \"\"];\n}\n\n/**\n * Column alignment options\n */\nexport type ColumnAlign = \"left\" | \"center\" | \"right\";\n\n/**\n * Column definition for table\n */\nexport interface TableColumn<T = Record<string, unknown>> {\n /** Column key in the data object */\n key: keyof T;\n /** Display header text */\n header: string;\n /** Column alignment (default: left) */\n align?: ColumnAlign;\n /** Fixed column width (auto-calculated if not specified) */\n width?: number;\n /** Custom formatter function for cell values */\n formatter?: (value: unknown, row: T) => string;\n}\n\n/**\n * Configuration for table component\n */\nexport interface TableConfig<T = Record<string, unknown>> {\n /** Column definitions */\n columns: TableColumn<T>[];\n /** Data rows */\n rows: T[];\n /** Show header row (default: true) */\n showHeader?: boolean;\n /** Show borders (default: true in TTY mode) */\n showBorders?: boolean;\n /** Table title (optional) */\n title?: string;\n}\n\n/**\n * Align text within a given width\n */\nfunction alignText(text: string, width: number, align: ColumnAlign): string {\n const textLength = stripAnsi(text).length;\n const padding = Math.max(0, width - textLength);\n\n switch (align) {\n case \"right\":\n return \" \".repeat(padding) + text;\n case \"center\": {\n const leftPad = Math.floor(padding / 2);\n const rightPad = padding - leftPad;\n return \" \".repeat(leftPad) + text + \" \".repeat(rightPad);\n }\n default:\n return text + \" \".repeat(padding);\n }\n}\n\n/**\n * Strip ANSI escape codes from string for length calculation\n */\nfunction stripAnsi(str: string): string {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI codes regex\n return str.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\n/**\n * Calculate column widths based on content\n */\nfunction calculateColumnWidths<T>(\n columns: TableColumn<T>[],\n rows: T[],\n showHeader: boolean,\n): number[] {\n return columns.map((col) => {\n // Use fixed width if specified\n if (col.width !== undefined) {\n return col.width;\n }\n\n // Calculate max width from header and data\n let maxWidth = showHeader ? col.header.length : 0;\n\n for (const row of rows) {\n const value = row[col.key];\n const formatted = col.formatter\n ? col.formatter(value, row)\n : String(value ?? \"\");\n const length = stripAnsi(formatted).length;\n maxWidth = Math.max(maxWidth, length);\n }\n\n return maxWidth;\n });\n}\n\n/**\n * Format a single cell value\n */\nfunction formatCell<T>(value: unknown, row: T, column: TableColumn<T>): string {\n if (column.formatter) {\n return column.formatter(value, row);\n }\n\n if (value === null || value === undefined) {\n return colors.dim(\"-\");\n }\n\n return String(value);\n}\n\n/**\n * Render table in TTY mode with borders and styling\n */\nfunction renderTTY<T>(config: TableConfig<T>): string {\n const {\n columns,\n rows,\n showHeader = true,\n showBorders = true,\n title,\n } = config;\n const lines: string[] = [];\n\n // Calculate column widths\n const widths = calculateColumnWidths(columns, rows, showHeader);\n\n // Title\n lines.push(..._renderTitle(title, true));\n\n // Header row\n if (showHeader) {\n const headerCells = columns.map((col, i) => {\n const text = colors.cyan(colors.bold(col.header));\n return alignText(text, widths[i]!, col.align ?? \"left\");\n });\n\n lines.push(headerCells.join(\" \"));\n\n // Header separator\n if (showBorders) {\n const separatorParts = widths.map((w) => \"─\".repeat(w));\n lines.push(colors.gray(separatorParts.join(\"─\")));\n }\n }\n\n // Data rows\n for (const row of rows) {\n const cells = columns.map((col, i) => {\n const value = row[col.key];\n const formatted = formatCell(value, row, col);\n return alignText(formatted, widths[i]!, col.align ?? \"left\");\n });\n\n lines.push(cells.join(\" \"));\n }\n\n // Bottom border (optional)\n if (showBorders && rows.length > 0) {\n const separatorParts = widths.map((w) => \"─\".repeat(w));\n lines.push(colors.gray(separatorParts.join(\"─\")));\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render table in non-TTY mode (plain text)\n */\nfunction renderPlain<T>(config: TableConfig<T>): string {\n const { columns, rows, showHeader = true, title } = config;\n const lines: string[] = [];\n\n // Calculate column widths\n const widths = calculateColumnWidths(columns, rows, showHeader);\n\n // Title\n lines.push(..._renderTitle(title, false));\n\n // Header row\n if (showHeader) {\n const headerCells = columns.map((col, i) =>\n alignText(col.header, widths[i]!, col.align ?? \"left\"),\n );\n lines.push(headerCells.join(\" \"));\n\n // Separator\n const separator = columns.map((_, i) => \"-\".repeat(widths[i]!)).join(\" \");\n lines.push(separator);\n }\n\n // Data rows\n for (const row of rows) {\n const cells = columns.map((col, i) => {\n const value = row[col.key];\n const formatted = formatCell(value, row, col);\n return alignText(stripAnsi(formatted), widths[i]!, col.align ?? \"left\");\n });\n lines.push(cells.join(\" \"));\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Display a table with columns and rows\n *\n * @example\n * ```typescript\n * table({\n * title: \"Users\",\n * columns: [\n * { key: \"name\", header: \"Name\" },\n * { key: \"age\", header: \"Age\", align: \"right\" },\n * { key: \"status\", header: \"Status\", formatter: (val) =>\n * val === \"active\" ? colors.green(\"✓ Active\") : colors.red(\"✗ Inactive\")\n * },\n * ],\n * rows: [\n * { name: \"Alice\", age: 25, status: \"active\" },\n * { name: \"Bob\", age: 30, status: \"inactive\" },\n * ],\n * });\n * ```\n */\nexport function table<T = Record<string, unknown>>(\n config: TableConfig<T>,\n): void {\n const output = isTTY() ? renderTTY(config) : renderPlain(config);\n console.log(output);\n}\n"],"mappings":"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"}
|
package/dist/ui/index.d.mts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { confirm } from "./components/confirm.mjs";
|
|
2
2
|
import { FormConfig, FormField, form } from "./components/form.mjs";
|
|
3
3
|
import { InputConfig, input } from "./components/input.mjs";
|
|
4
|
+
import { error, help, output } from "./components/log.mjs";
|
|
5
|
+
import "./components/prompts.mjs";
|
|
4
6
|
import { SelectConfig, SelectOption, select } from "./components/select.mjs";
|
|
5
7
|
import { SpinnerHandle, spinner } from "./components/spinner.mjs";
|
|
6
8
|
import { ColumnAlign, TableColumn, TableConfig, table } from "./components/table.mjs";
|
|
7
|
-
import { AnsiColor,
|
|
8
|
-
import { error, help, output } from "./utils/output.mjs";
|
|
9
|
+
import { AnsiColor, colors, formatText, theme } from "./utils/colors.mjs";
|
|
9
10
|
import { isTTY } from "./utils/tty.mjs";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ExitWarning } from "../../shared/errors.mjs";
|
|
2
|
+
import * as p from "@clack/prompts";
|
|
3
|
+
|
|
4
|
+
//#region src/ui/utils/cancel.ts
|
|
5
|
+
/**
|
|
6
|
+
* Handle cancel action for prompts
|
|
7
|
+
* If the value is a cancel symbol, throws ExitWarning
|
|
8
|
+
* Otherwise returns the value
|
|
9
|
+
*/
|
|
10
|
+
function handleCancel(value) {
|
|
11
|
+
if (p.isCancel(value)) throw new ExitWarning();
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { handleCancel };
|
|
17
|
+
//# sourceMappingURL=cancel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancel.mjs","names":[],"sources":["../../../src/ui/utils/cancel.ts"],"sourcesContent":["import * as p from \"@clack/prompts\";\nimport { ExitWarning } from \"../../shared/errors\";\n\n/**\n * Handle cancel action for prompts\n * If the value is a cancel symbol, throws ExitWarning\n * Otherwise returns the value\n */\nexport function handleCancel<T>(value: T | symbol): T {\n if (p.isCancel(value)) {\n throw new ExitWarning();\n }\n return value;\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,aAAgB,OAAsB;AACpD,KAAI,EAAE,SAAS,MAAM,CACnB,OAAM,IAAI,aAAa;AAEzB,QAAO"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as colors from "xycolors";
|
|
2
2
|
|
|
3
3
|
//#region src/ui/utils/colors.d.ts
|
|
4
4
|
|
|
@@ -24,7 +24,7 @@ declare const theme: {
|
|
|
24
24
|
};
|
|
25
25
|
type AnsiColor = "red" | "green" | "yellow" | "blue" | "magenta" | "cyan" | "white" | "gray";
|
|
26
26
|
/**
|
|
27
|
-
* Format text with
|
|
27
|
+
* Format text with xycolors
|
|
28
28
|
*/
|
|
29
29
|
declare function formatText(text: string, options?: {
|
|
30
30
|
color?: AnsiColor;
|
|
@@ -34,5 +34,5 @@ declare function formatText(text: string, options?: {
|
|
|
34
34
|
underline?: boolean;
|
|
35
35
|
}): string;
|
|
36
36
|
//#endregion
|
|
37
|
-
export { AnsiColor,
|
|
37
|
+
export { AnsiColor, colors, formatText, theme };
|
|
38
38
|
//# sourceMappingURL=colors.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"colors.d.mts","names":[],"sources":["../../../src/ui/utils/colors.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAuBY,cAvBC,KAuBQ,EAAA;
|
|
1
|
+
{"version":3,"file":"colors.d.mts","names":[],"sources":["../../../src/ui/utils/colors.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAuBY,cAvBC,KAuBQ,EAAA;EA2BL,SAAA,OAAU,EAAA,SAGd;;;;;;;;;;;;;;;;KA9BA,SAAA;;;;iBA2BI,UAAA;UAGJ"}
|
package/dist/ui/utils/colors.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as colors from "xycolors";
|
|
2
2
|
|
|
3
3
|
//#region src/ui/utils/colors.ts
|
|
4
4
|
/**
|
|
@@ -22,43 +22,31 @@ const theme = {
|
|
|
22
22
|
disabled: "#6e7681"
|
|
23
23
|
};
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* Color mapping for formatText function
|
|
26
|
+
*/
|
|
27
|
+
const colorMap = {
|
|
28
|
+
red: colors.red,
|
|
29
|
+
green: colors.green,
|
|
30
|
+
yellow: colors.yellow,
|
|
31
|
+
blue: colors.blue,
|
|
32
|
+
magenta: colors.magenta,
|
|
33
|
+
cyan: colors.cyan,
|
|
34
|
+
white: colors.white,
|
|
35
|
+
gray: colors.gray
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Format text with xycolors
|
|
26
39
|
*/
|
|
27
40
|
function formatText(text, options) {
|
|
28
41
|
let result = text;
|
|
29
|
-
if (options?.color)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
result = pc$1.green(result);
|
|
35
|
-
break;
|
|
36
|
-
case "yellow":
|
|
37
|
-
result = pc$1.yellow(result);
|
|
38
|
-
break;
|
|
39
|
-
case "blue":
|
|
40
|
-
result = pc$1.blue(result);
|
|
41
|
-
break;
|
|
42
|
-
case "magenta":
|
|
43
|
-
result = pc$1.magenta(result);
|
|
44
|
-
break;
|
|
45
|
-
case "cyan":
|
|
46
|
-
result = pc$1.cyan(result);
|
|
47
|
-
break;
|
|
48
|
-
case "white":
|
|
49
|
-
result = pc$1.white(result);
|
|
50
|
-
break;
|
|
51
|
-
case "gray":
|
|
52
|
-
result = pc$1.gray(result);
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
if (options?.bold) result = pc$1.bold(result);
|
|
56
|
-
if (options?.dim) result = pc$1.dim(result);
|
|
57
|
-
if (options?.italic) result = pc$1.italic(result);
|
|
58
|
-
if (options?.underline) result = pc$1.underline(result);
|
|
42
|
+
if (options?.color) result = colorMap[options.color](result);
|
|
43
|
+
if (options?.bold) result = colors.bold(result);
|
|
44
|
+
if (options?.dim) result = colors.dim(result);
|
|
45
|
+
if (options?.italic) result = colors.italic(result);
|
|
46
|
+
if (options?.underline) result = colors.underline(result);
|
|
59
47
|
return result;
|
|
60
48
|
}
|
|
61
49
|
|
|
62
50
|
//#endregion
|
|
63
|
-
export {
|
|
51
|
+
export { colors, formatText, theme };
|
|
64
52
|
//# sourceMappingURL=colors.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"colors.mjs","names":["
|
|
1
|
+
{"version":3,"file":"colors.mjs","names":["colorMap: Record<AnsiColor, (text: string) => string>"],"sources":["../../../src/ui/utils/colors.ts"],"sourcesContent":["import * as colors from \"xycolors\";\n\n/**\n * Default color theme for UI components (hex values for reference)\n */\nexport const theme = {\n // Brand colors\n primary: \"#3b82f6\", // Blue\n success: \"#10b981\", // Green\n warning: \"#f59e0b\", // Orange\n error: \"#ef4444\", // Red\n info: \"#06b6d4\", // Cyan\n\n // UI colors\n background: \"#161b22\", // Dark gray\n surface: \"#1e293b\", // Lighter gray\n border: \"#30363d\", // Border gray\n text: \"#c9d1d9\", // Light text\n textDim: \"#8b949e\", // Dimmed text\n textBright: \"#ffffff\", // Bright text\n\n // Interactive states\n focused: \"#3b82f6\", // Blue\n selected: \"#3b82f6\", // Blue\n hover: \"#334155\", // Lighter gray\n disabled: \"#6e7681\", // Muted gray\n} as const;\n\nexport type AnsiColor =\n | \"red\"\n | \"green\"\n | \"yellow\"\n | \"blue\"\n | \"magenta\"\n | \"cyan\"\n | \"white\"\n | \"gray\";\n\n/**\n * Color mapping for formatText function\n */\nconst colorMap: Record<AnsiColor, (text: string) => string> = {\n red: colors.red,\n green: colors.green,\n yellow: colors.yellow,\n blue: colors.blue,\n magenta: colors.magenta,\n cyan: colors.cyan,\n white: colors.white,\n gray: colors.gray,\n};\n\n/**\n * Format text with xycolors\n */\nexport function formatText(\n text: string,\n options?: {\n color?: AnsiColor;\n bold?: boolean;\n dim?: boolean;\n italic?: boolean;\n underline?: boolean;\n },\n): string {\n let result = text;\n\n // Apply color first\n if (options?.color) {\n result = colorMap[options.color](result);\n }\n\n // Apply styles\n if (options?.bold) result = colors.bold(result);\n if (options?.dim) result = colors.dim(result);\n if (options?.italic) result = colors.italic(result);\n if (options?.underline) result = colors.underline(result);\n\n return result;\n}\n\nexport { colors };\n"],"mappings":";;;;;;AAKA,MAAa,QAAQ;CAEnB,SAAS;CACT,SAAS;CACT,SAAS;CACT,OAAO;CACP,MAAM;CAGN,YAAY;CACZ,SAAS;CACT,QAAQ;CACR,MAAM;CACN,SAAS;CACT,YAAY;CAGZ,SAAS;CACT,UAAU;CACV,OAAO;CACP,UAAU;CACX;;;;AAeD,MAAMA,WAAwD;CAC5D,KAAK,OAAO;CACZ,OAAO,OAAO;CACd,QAAQ,OAAO;CACf,MAAM,OAAO;CACb,SAAS,OAAO;CAChB,MAAM,OAAO;CACb,OAAO,OAAO;CACd,MAAM,OAAO;CACd;;;;AAKD,SAAgB,WACd,MACA,SAOQ;CACR,IAAI,SAAS;AAGb,KAAI,SAAS,MACX,UAAS,SAAS,QAAQ,OAAO,OAAO;AAI1C,KAAI,SAAS,KAAM,UAAS,OAAO,KAAK,OAAO;AAC/C,KAAI,SAAS,IAAK,UAAS,OAAO,IAAI,OAAO;AAC7C,KAAI,SAAS,OAAQ,UAAS,OAAO,OAAO,OAAO;AACnD,KAAI,SAAS,UAAW,UAAS,OAAO,UAAU,OAAO;AAEzD,QAAO"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kly",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [],
|
|
@@ -41,35 +41,37 @@
|
|
|
41
41
|
"lint": "biome check --write --unsafe ./src && nr typecheck",
|
|
42
42
|
"prepublishOnly": "nr build",
|
|
43
43
|
"release": "release-it",
|
|
44
|
-
"start": "bun run
|
|
44
|
+
"start": "bun run bin/kly.ts",
|
|
45
45
|
"test": "bun test",
|
|
46
46
|
"up": "taze major -I",
|
|
47
47
|
"prepare": "simple-git-hooks"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@ai-sdk/anthropic": "^3.0.
|
|
51
|
-
"@ai-sdk/deepseek": "^2.0.
|
|
52
|
-
"@ai-sdk/google": "^3.0.
|
|
53
|
-
"@ai-sdk/mistral": "^3.0.
|
|
54
|
-
"@ai-sdk/openai": "^3.0.
|
|
50
|
+
"@ai-sdk/anthropic": "^3.0.2",
|
|
51
|
+
"@ai-sdk/deepseek": "^2.0.2",
|
|
52
|
+
"@ai-sdk/google": "^3.0.2",
|
|
53
|
+
"@ai-sdk/mistral": "^3.0.2",
|
|
54
|
+
"@ai-sdk/openai": "^3.0.2",
|
|
55
55
|
"@anthropic-ai/sandbox-runtime": "^0.0.23",
|
|
56
56
|
"@clack/prompts": "1.0.0-alpha.9",
|
|
57
57
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
58
|
-
"ai": "^6.0.
|
|
59
|
-
"
|
|
60
|
-
"
|
|
58
|
+
"ai": "^6.0.6",
|
|
59
|
+
"js-yaml": "^4.1.1",
|
|
60
|
+
"xycolors": "^0.1.2",
|
|
61
|
+
"zod": "^4.3.4"
|
|
61
62
|
},
|
|
62
63
|
"devDependencies": {
|
|
63
64
|
"@antfu/ni": "^28.0.0",
|
|
64
65
|
"@biomejs/biome": "^2.3.10",
|
|
65
66
|
"@release-it/conventional-changelog": "^10.0.4",
|
|
66
67
|
"@types/bun": "^1.3.5",
|
|
68
|
+
"@types/js-yaml": "^4.0.9",
|
|
67
69
|
"lint-staged": "^16.2.7",
|
|
68
70
|
"publint": "^0.3.16",
|
|
69
|
-
"release-it": "^19.2.
|
|
71
|
+
"release-it": "^19.2.2",
|
|
70
72
|
"simple-git-hooks": "^2.13.1",
|
|
71
73
|
"taze": "^19.9.2",
|
|
72
|
-
"tsdown": "^0.18.
|
|
74
|
+
"tsdown": "^0.18.4",
|
|
73
75
|
"typescript": "^5.9.3"
|
|
74
76
|
},
|
|
75
77
|
"simple-git-hooks": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"permissions-extractor-BfUPS0Tr.mjs","names":[],"sources":["../../src/remote/permissions-extractor.ts"],"sourcesContent":["import type { AppPermissions } from \"../types\";\n\n/**\n * Extract declared permissions from a remote app\n *\n * This function safely loads the app definition to read its declared permissions\n * WITHOUT executing the actual tool logic.\n *\n * @param entryPath - Absolute path to the app entry point\n * @returns Declared permissions or undefined if not specified\n */\nexport async function extractAppPermissions(\n entryPath: string,\n): Promise<AppPermissions | undefined> {\n try {\n // Temporarily mark as programmatic mode to avoid triggering CLI logic\n const prevProgrammatic = process.env.KLY_PROGRAMMATIC;\n process.env.KLY_PROGRAMMATIC = \"true\";\n\n // Dynamic import to load the app module\n const appModule = await import(entryPath);\n\n // Restore environment\n if (prevProgrammatic === undefined) {\n delete process.env.KLY_PROGRAMMATIC;\n } else {\n process.env.KLY_PROGRAMMATIC = prevProgrammatic;\n }\n\n // The app module should export a KlyApp instance\n // which has a definition.permissions field\n if (appModule.default?.definition) {\n return appModule.default.definition.permissions;\n }\n\n // Some apps might export the app directly\n if (appModule.definition) {\n return appModule.definition.permissions;\n }\n\n return undefined;\n } catch (error) {\n // If we can't extract permissions, return undefined\n // The calling code will fall back to asking for all permissions\n console.warn(\n `⚠️ Could not extract permissions from app (${error instanceof Error ? error.message : \"unknown error\"})`,\n );\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;;AAWA,eAAsB,sBACpB,WACqC;AACrC,KAAI;EAEF,MAAM,mBAAmB,QAAQ,IAAI;AACrC,UAAQ,IAAI,mBAAmB;EAG/B,MAAM,YAAY,MAAM,OAAO;AAG/B,MAAI,qBAAqB,OACvB,QAAO,QAAQ,IAAI;MAEnB,SAAQ,IAAI,mBAAmB;AAKjC,MAAI,UAAU,SAAS,WACrB,QAAO,UAAU,QAAQ,WAAW;AAItC,MAAI,UAAU,WACZ,QAAO,UAAU,WAAW;AAG9B;UACO,OAAO;AAGd,UAAQ,KACN,+CAA+C,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB,GACzG;AACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.mts","names":[],"sources":["../../../src/ui/utils/output.ts"],"sourcesContent":[],"mappings":";;AAOA;AAkBA;AAmBA;;iBArCgB,MAAA;;;;;;;iBAkBA,KAAA;;;;;;iBAmBA,IAAA"}
|