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.

Files changed (71) hide show
  1. package/dist/ai/storage.mjs +3 -2
  2. package/dist/ai/storage.mjs.map +1 -1
  3. package/dist/bin/bin-registry-DOBspniG.mjs +3 -0
  4. package/dist/bin/kly.mjs +3217 -2430
  5. package/dist/bin/kly.mjs.map +1 -1
  6. package/dist/bin/{permissions-extractor-BfUPS0Tr.mjs → permissions-extractor-ySRyhQut.mjs} +4 -2
  7. package/dist/bin/permissions-extractor-ySRyhQut.mjs.map +1 -0
  8. package/dist/bin/remote-tQeFZX9o.mjs +3 -0
  9. package/dist/cli.mjs +4 -4
  10. package/dist/cli.mjs.map +1 -1
  11. package/dist/define-app.d.mts.map +1 -1
  12. package/dist/define-app.mjs +35 -28
  13. package/dist/define-app.mjs.map +1 -1
  14. package/dist/index.d.mts +3 -3
  15. package/dist/index.mjs +3 -3
  16. package/dist/mcp/schema-converter.d.mts.map +1 -1
  17. package/dist/mcp/schema-converter.mjs +2 -1
  18. package/dist/mcp/schema-converter.mjs.map +1 -1
  19. package/dist/mcp/server.d.mts.map +1 -1
  20. package/dist/mcp/server.mjs +7 -6
  21. package/dist/mcp/server.mjs.map +1 -1
  22. package/dist/permissions/index.mjs +8 -10
  23. package/dist/permissions/index.mjs.map +1 -1
  24. package/dist/sandbox/bundled-executor.d.mts.map +1 -1
  25. package/dist/sandbox/bundled-executor.mjs +67 -10
  26. package/dist/sandbox/bundled-executor.mjs.map +1 -1
  27. package/dist/sandbox/ipc-client.mjs +2 -0
  28. package/dist/sandbox/ipc-client.mjs.map +1 -1
  29. package/dist/shared/constants.mjs +5 -1
  30. package/dist/shared/constants.mjs.map +1 -1
  31. package/dist/shared/errors.mjs +21 -0
  32. package/dist/shared/errors.mjs.map +1 -0
  33. package/dist/types.d.mts +7 -6
  34. package/dist/types.d.mts.map +1 -1
  35. package/dist/types.mjs.map +1 -1
  36. package/dist/ui/components/confirm.d.mts.map +1 -1
  37. package/dist/ui/components/confirm.mjs +4 -8
  38. package/dist/ui/components/confirm.mjs.map +1 -1
  39. package/dist/ui/components/form.d.mts.map +1 -1
  40. package/dist/ui/components/form.mjs +12 -26
  41. package/dist/ui/components/form.mjs.map +1 -1
  42. package/dist/ui/components/input.d.mts.map +1 -1
  43. package/dist/ui/components/input.mjs +3 -7
  44. package/dist/ui/components/input.mjs.map +1 -1
  45. package/dist/ui/{utils/output.d.mts → components/log.d.mts} +22 -2
  46. package/dist/ui/components/log.d.mts.map +1 -0
  47. package/dist/ui/components/log.mjs +92 -0
  48. package/dist/ui/components/log.mjs.map +1 -0
  49. package/dist/ui/components/prompts.d.mts +1 -0
  50. package/dist/ui/components/select.d.mts.map +1 -1
  51. package/dist/ui/components/select.mjs +5 -8
  52. package/dist/ui/components/select.mjs.map +1 -1
  53. package/dist/ui/components/table.d.mts +1 -1
  54. package/dist/ui/components/table.d.mts.map +1 -1
  55. package/dist/ui/components/table.mjs +19 -19
  56. package/dist/ui/components/table.mjs.map +1 -1
  57. package/dist/ui/index.d.mts +3 -2
  58. package/dist/ui/utils/cancel.mjs +17 -0
  59. package/dist/ui/utils/cancel.mjs.map +1 -0
  60. package/dist/ui/utils/colors.d.mts +3 -3
  61. package/dist/ui/utils/colors.d.mts.map +1 -1
  62. package/dist/ui/utils/colors.mjs +21 -33
  63. package/dist/ui/utils/colors.mjs.map +1 -1
  64. package/package.json +14 -12
  65. package/dist/bin/permissions-extractor-BfUPS0Tr.mjs.map +0 -1
  66. package/dist/ui/utils/output.d.mts.map +0 -1
  67. package/dist/ui/utils/output.mjs +0 -42
  68. package/dist/ui/utils/output.mjs.map +0 -1
  69. /package/dist/bin/{config-builder-D5EtwOB3.mjs → config-builder-VSUaGlaV.mjs} +0 -0
  70. /package/dist/bin/{launcher-Ex3ynZdE.mjs → launcher-DD6vpEFb.mjs} +0 -0
  71. /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 if (p.isCancel(result)) {\n p.cancel(\"Operation cancelled\");\n process.exit(0);\n }\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA8BA,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;;CAGH,MAAM,SAAS,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;AAEF,KAAI,EAAE,SAAS,OAAO,EAAE;AACtB,IAAE,OAAO,sBAAsB;AAC/B,UAAQ,KAAK,EAAE;;AAGjB,QAAO"}
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/utils/output.d.ts
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=output.d.mts.map
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":";;AAQA;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
+ {"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
- const result = await p.select({
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 if (p.isCancel(result)) {\n p.cancel(\"Operation cancelled\");\n process.exit(0);\n }\n\n return result as T;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA2CA,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;EACjD,EAAE;CAEH,MAAM,SAAS,MAAM,EAAE,OAAO;EAC5B,SAAS,OAAO,UAAU;EAC1B,SAAS;EACV,CAAC;AAEF,KAAI,EAAE,SAAS,OAAO,EAAE;AACtB,IAAE,OAAO,sBAAsB;AAC/B,UAAQ,KAAK,EAAE;;AAGjB,QAAO"}
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" ? pc.green("✓ Active") : pc.red("✗ Inactive")
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":";;AAMA;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;EA4MO;EAAU,KAAA,CAAA,EAAA,MAAA;EACJ;EAAZ,SAAA,CAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAAA,EAvN0B,CAuN1B,EAAA,GAAA,MAAA;;;;;UAjNO,gBAAgB;;WAEtB,YAAY;;QAEf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4MQ,UAAU,iCAChB,YAAY"}
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 { formatText, pc } from "../utils/colors.mjs";
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 pc.dim("-");
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
- if (title) {
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(formatText(col.header, {
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(pc.gray(separatorParts.join("─")));
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(pc.gray(separatorParts.join("─")));
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
- if (title) {
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" ? pc.green("✓ Active") : pc.red("✗ Inactive")
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 { formatText, pc } from \"../utils/colors\";\nimport { isTTY } from \"../utils/tty\";\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 pc.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 if (title) {\n lines.push(\"\");\n lines.push(formatText(`${title}`, { bold: true }));\n lines.push(\"\");\n }\n\n // Header row\n if (showHeader) {\n const headerCells = columns.map((col, i) => {\n const text = formatText(col.header, { bold: true, color: \"cyan\" });\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(pc.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(pc.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 if (title) {\n lines.push(\"\");\n lines.push(title);\n lines.push(\"\");\n }\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\" ? pc.green(\"✓ Active\") : pc.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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"}
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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"}
@@ -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, formatText, pc, theme } from "./utils/colors.mjs";
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 pc$1 from "picocolors";
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 picocolors
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, formatText, pc$1 as pc, theme };
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;EAaL,SAAA,OAAU,EAAA,SAGd;;;;;;;;;;;;;;;;KAhBA,SAAA;;;;iBAaI,UAAA;UAGJ"}
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"}
@@ -1,4 +1,4 @@
1
- import pc$1 from "picocolors";
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
- * Format text with picocolors
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) switch (options.color) {
30
- case "red":
31
- result = pc$1.red(result);
32
- break;
33
- case "green":
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 { formatText, pc$1 as pc, theme };
51
+ export { colors, formatText, theme };
64
52
  //# sourceMappingURL=colors.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"colors.mjs","names":["pc"],"sources":["../../../src/ui/utils/colors.ts"],"sourcesContent":["import pc from \"picocolors\";\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 * Format text with picocolors\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 switch (options.color) {\n case \"red\":\n result = pc.red(result);\n break;\n case \"green\":\n result = pc.green(result);\n break;\n case \"yellow\":\n result = pc.yellow(result);\n break;\n case \"blue\":\n result = pc.blue(result);\n break;\n case \"magenta\":\n result = pc.magenta(result);\n break;\n case \"cyan\":\n result = pc.cyan(result);\n break;\n case \"white\":\n result = pc.white(result);\n break;\n case \"gray\":\n result = pc.gray(result);\n break;\n }\n }\n\n // Apply styles\n if (options?.bold) result = pc.bold(result);\n if (options?.dim) result = pc.dim(result);\n if (options?.italic) result = pc.italic(result);\n if (options?.underline) result = pc.underline(result);\n\n return result;\n}\n\n// Re-export picocolors for direct usage\nexport { pc };\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,SAAgB,WACd,MACA,SAOQ;CACR,IAAI,SAAS;AAGb,KAAI,SAAS,MACX,SAAQ,QAAQ,OAAhB;EACE,KAAK;AACH,YAASA,KAAG,IAAI,OAAO;AACvB;EACF,KAAK;AACH,YAASA,KAAG,MAAM,OAAO;AACzB;EACF,KAAK;AACH,YAASA,KAAG,OAAO,OAAO;AAC1B;EACF,KAAK;AACH,YAASA,KAAG,KAAK,OAAO;AACxB;EACF,KAAK;AACH,YAASA,KAAG,QAAQ,OAAO;AAC3B;EACF,KAAK;AACH,YAASA,KAAG,KAAK,OAAO;AACxB;EACF,KAAK;AACH,YAASA,KAAG,MAAM,OAAO;AACzB;EACF,KAAK;AACH,YAASA,KAAG,KAAK,OAAO;AACxB;;AAKN,KAAI,SAAS,KAAM,UAASA,KAAG,KAAK,OAAO;AAC3C,KAAI,SAAS,IAAK,UAASA,KAAG,IAAI,OAAO;AACzC,KAAI,SAAS,OAAQ,UAASA,KAAG,OAAO,OAAO;AAC/C,KAAI,SAAS,UAAW,UAASA,KAAG,UAAU,OAAO;AAErD,QAAO"}
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.2.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 src/index.ts",
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.1",
51
- "@ai-sdk/deepseek": "^2.0.1",
52
- "@ai-sdk/google": "^3.0.1",
53
- "@ai-sdk/mistral": "^3.0.1",
54
- "@ai-sdk/openai": "^3.0.1",
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.3",
59
- "picocolors": "^1.1.1",
60
- "zod": "^4.2.1"
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.1",
71
+ "release-it": "^19.2.2",
70
72
  "simple-git-hooks": "^2.13.1",
71
73
  "taze": "^19.9.2",
72
- "tsdown": "^0.18.3",
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"}