@chanl-ai/cli 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/bin/chanl.js +10 -0
  2. package/dist/__tests__/cli.test.d.ts +2 -0
  3. package/dist/__tests__/cli.test.js +2313 -0
  4. package/dist/__tests__/cli.test.js.map +1 -0
  5. package/dist/cli.d.ts +12 -0
  6. package/dist/cli.js +72 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/agents.d.ts +8 -0
  9. package/dist/commands/agents.js +671 -0
  10. package/dist/commands/agents.js.map +1 -0
  11. package/dist/commands/auth.d.ts +16 -0
  12. package/dist/commands/auth.js +294 -0
  13. package/dist/commands/auth.js.map +1 -0
  14. package/dist/commands/call.d.ts +8 -0
  15. package/dist/commands/call.js +166 -0
  16. package/dist/commands/call.js.map +1 -0
  17. package/dist/commands/calls.d.ts +8 -0
  18. package/dist/commands/calls.js +719 -0
  19. package/dist/commands/calls.js.map +1 -0
  20. package/dist/commands/chat.d.ts +8 -0
  21. package/dist/commands/chat.js +203 -0
  22. package/dist/commands/chat.js.map +1 -0
  23. package/dist/commands/config.d.ts +8 -0
  24. package/dist/commands/config.js +231 -0
  25. package/dist/commands/config.js.map +1 -0
  26. package/dist/commands/health.d.ts +8 -0
  27. package/dist/commands/health.js +55 -0
  28. package/dist/commands/health.js.map +1 -0
  29. package/dist/commands/index.d.ts +18 -0
  30. package/dist/commands/index.js +39 -0
  31. package/dist/commands/index.js.map +1 -0
  32. package/dist/commands/knowledge.d.ts +8 -0
  33. package/dist/commands/knowledge.js +539 -0
  34. package/dist/commands/knowledge.js.map +1 -0
  35. package/dist/commands/mcp.d.ts +8 -0
  36. package/dist/commands/mcp.js +589 -0
  37. package/dist/commands/mcp.js.map +1 -0
  38. package/dist/commands/memory.d.ts +8 -0
  39. package/dist/commands/memory.js +408 -0
  40. package/dist/commands/memory.js.map +1 -0
  41. package/dist/commands/personas.d.ts +8 -0
  42. package/dist/commands/personas.js +356 -0
  43. package/dist/commands/personas.js.map +1 -0
  44. package/dist/commands/prompts.d.ts +8 -0
  45. package/dist/commands/prompts.js +295 -0
  46. package/dist/commands/prompts.js.map +1 -0
  47. package/dist/commands/scenarios.d.ts +8 -0
  48. package/dist/commands/scenarios.js +591 -0
  49. package/dist/commands/scenarios.js.map +1 -0
  50. package/dist/commands/scorecards.d.ts +8 -0
  51. package/dist/commands/scorecards.js +570 -0
  52. package/dist/commands/scorecards.js.map +1 -0
  53. package/dist/commands/tools.d.ts +8 -0
  54. package/dist/commands/tools.js +632 -0
  55. package/dist/commands/tools.js.map +1 -0
  56. package/dist/commands/toolsets.d.ts +8 -0
  57. package/dist/commands/toolsets.js +464 -0
  58. package/dist/commands/toolsets.js.map +1 -0
  59. package/dist/commands/workspaces.d.ts +8 -0
  60. package/dist/commands/workspaces.js +170 -0
  61. package/dist/commands/workspaces.js.map +1 -0
  62. package/dist/index.d.ts +2 -0
  63. package/dist/index.js +6 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/utils/config-store.d.ts +117 -0
  66. package/dist/utils/config-store.js +191 -0
  67. package/dist/utils/config-store.js.map +1 -0
  68. package/dist/utils/interactive.d.ts +41 -0
  69. package/dist/utils/interactive.js +83 -0
  70. package/dist/utils/interactive.js.map +1 -0
  71. package/dist/utils/output.d.ts +100 -0
  72. package/dist/utils/output.js +221 -0
  73. package/dist/utils/output.js.map +1 -0
  74. package/dist/utils/sdk-factory.d.ts +15 -0
  75. package/dist/utils/sdk-factory.js +34 -0
  76. package/dist/utils/sdk-factory.js.map +1 -0
  77. package/package.json +67 -0
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Output formatting options
3
+ */
4
+ interface OutputOptions {
5
+ json?: boolean;
6
+ noColor?: boolean;
7
+ }
8
+ /**
9
+ * Set global output options
10
+ */
11
+ declare function setOutputOptions(options: OutputOptions): void;
12
+ /**
13
+ * Get current output options
14
+ */
15
+ declare function getOutputOptions(): OutputOptions;
16
+ /**
17
+ * Check if JSON output is enabled
18
+ */
19
+ declare function isJsonOutput(): boolean;
20
+ /**
21
+ * Print JSON output
22
+ */
23
+ declare function printJson(data: unknown): void;
24
+ /**
25
+ * Print success message with checkmark
26
+ */
27
+ declare function printSuccess(message: string): void;
28
+ /**
29
+ * Print error message with X mark
30
+ */
31
+ declare function printError(message: string, details?: string): void;
32
+ /**
33
+ * Print warning message
34
+ */
35
+ declare function printWarning(message: string): void;
36
+ /**
37
+ * Print info message
38
+ */
39
+ declare function printInfo(message: string): void;
40
+ /**
41
+ * Print a labeled value
42
+ */
43
+ declare function printLabel(label: string, value: string | number | boolean): void;
44
+ /**
45
+ * Print a header/title
46
+ */
47
+ declare function printHeader(title: string): void;
48
+ /**
49
+ * Print a blank line
50
+ */
51
+ declare function printBlank(): void;
52
+ /**
53
+ * Table column definition
54
+ */
55
+ interface TableColumn {
56
+ header: string;
57
+ key: string;
58
+ width?: number;
59
+ align?: 'left' | 'right' | 'center';
60
+ format?: (value: unknown) => string;
61
+ }
62
+ /**
63
+ * Print a simple table
64
+ */
65
+ declare function printTable<T extends Record<string, unknown>>(columns: TableColumn[], rows: T[]): void;
66
+ /**
67
+ * Format a boolean as checkmark or X
68
+ */
69
+ declare function formatBoolean(value: unknown): string;
70
+ /**
71
+ * Format a date relative to now
72
+ */
73
+ declare function formatRelativeDate(dateStr: string | Date | undefined): string;
74
+ /**
75
+ * Truncate string with ellipsis
76
+ */
77
+ declare function truncate(str: string, maxLength: number): string;
78
+ /**
79
+ * Mask sensitive string (show first and last few characters)
80
+ */
81
+ declare function maskString(str: string, showFirst?: number, showLast?: number): string;
82
+ /**
83
+ * Format duration in milliseconds
84
+ */
85
+ declare function formatDuration(ms: number | undefined): string;
86
+ /**
87
+ * Format status with color
88
+ */
89
+ declare function formatStatus(status: string): string;
90
+ /**
91
+ * Format a date as a short date string
92
+ */
93
+ declare function formatDate(dateStr: string | Date | undefined): string;
94
+ /**
95
+ * Print a simple table from header and row arrays
96
+ * Simplified version for string[][] data
97
+ */
98
+ declare function printSimpleTable(headers: string[], rows: string[][]): void;
99
+
100
+ export { type OutputOptions, type TableColumn, formatBoolean, formatDate, formatDuration, formatRelativeDate, formatStatus, getOutputOptions, isJsonOutput, maskString, printBlank, printError, printHeader, printInfo, printJson, printLabel, printSimpleTable, printSuccess, printTable, printWarning, setOutputOptions, truncate };
@@ -0,0 +1,221 @@
1
+ import chalk from "chalk";
2
+ let globalOptions = {};
3
+ function setOutputOptions(options) {
4
+ globalOptions = { ...globalOptions, ...options };
5
+ }
6
+ function getOutputOptions() {
7
+ return globalOptions;
8
+ }
9
+ function isJsonOutput() {
10
+ return globalOptions.json === true;
11
+ }
12
+ function printJson(data) {
13
+ console.log(JSON.stringify(data, null, 2));
14
+ }
15
+ function printSuccess(message) {
16
+ if (isJsonOutput()) return;
17
+ console.log(chalk.green("\u2713"), message);
18
+ }
19
+ function printError(message, details) {
20
+ if (isJsonOutput()) {
21
+ printJson({ error: message, details });
22
+ return;
23
+ }
24
+ console.error(chalk.red("\u2717"), chalk.red("Error:"), message);
25
+ if (details) {
26
+ console.error(" ", chalk.dim(details));
27
+ }
28
+ }
29
+ function printWarning(message) {
30
+ if (isJsonOutput()) return;
31
+ console.log(chalk.yellow("!"), chalk.yellow("Warning:"), message);
32
+ }
33
+ function printInfo(message) {
34
+ if (isJsonOutput()) return;
35
+ console.log(chalk.blue("\u2139"), message);
36
+ }
37
+ function printLabel(label, value) {
38
+ if (isJsonOutput()) return;
39
+ console.log(chalk.dim(label + ":"), value);
40
+ }
41
+ function printHeader(title) {
42
+ if (isJsonOutput()) return;
43
+ console.log();
44
+ console.log(chalk.bold(title));
45
+ console.log(chalk.dim("\u2500".repeat(title.length)));
46
+ }
47
+ function printBlank() {
48
+ if (isJsonOutput()) return;
49
+ console.log();
50
+ }
51
+ function printTable(columns, rows) {
52
+ if (isJsonOutput()) {
53
+ printJson(rows);
54
+ return;
55
+ }
56
+ if (rows.length === 0) {
57
+ console.log(chalk.dim("No data to display"));
58
+ return;
59
+ }
60
+ const widths = columns.map((col) => {
61
+ const headerWidth = col.header.length;
62
+ const maxDataWidth = rows.reduce((max, row) => {
63
+ const value = col.format ? col.format(row[col.key]) : String(row[col.key] ?? "");
64
+ return Math.max(max, value.length);
65
+ }, 0);
66
+ return col.width ?? Math.max(headerWidth, maxDataWidth);
67
+ });
68
+ const headerLine = columns.map((col, i) => padString(col.header, widths[i] ?? 0, col.align)).join(" ");
69
+ console.log(chalk.bold(headerLine));
70
+ console.log(
71
+ chalk.dim(
72
+ widths.map((w) => "\u2500".repeat(w)).join("\u2500\u2500")
73
+ )
74
+ );
75
+ for (const row of rows) {
76
+ const rowLine = columns.map((col, i) => {
77
+ const value = col.format ? col.format(row[col.key]) : String(row[col.key] ?? "");
78
+ return padString(value, widths[i] ?? 0, col.align);
79
+ }).join(" ");
80
+ console.log(rowLine);
81
+ }
82
+ }
83
+ function padString(str, width, align = "left") {
84
+ const strLen = stripAnsi(str).length;
85
+ const padding = Math.max(0, width - strLen);
86
+ switch (align) {
87
+ case "right":
88
+ return " ".repeat(padding) + str;
89
+ case "center":
90
+ const leftPad = Math.floor(padding / 2);
91
+ const rightPad = padding - leftPad;
92
+ return " ".repeat(leftPad) + str + " ".repeat(rightPad);
93
+ default:
94
+ return str + " ".repeat(padding);
95
+ }
96
+ }
97
+ function stripAnsi(str) {
98
+ return str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "");
99
+ }
100
+ function formatBoolean(value) {
101
+ return value ? chalk.green("\u2713") : chalk.dim("\u2717");
102
+ }
103
+ function formatRelativeDate(dateStr) {
104
+ if (!dateStr) return chalk.dim("Never");
105
+ const date = typeof dateStr === "string" ? new Date(dateStr) : dateStr;
106
+ const now = /* @__PURE__ */ new Date();
107
+ const diffMs = now.getTime() - date.getTime();
108
+ const diffSecs = Math.floor(diffMs / 1e3);
109
+ const diffMins = Math.floor(diffSecs / 60);
110
+ const diffHours = Math.floor(diffMins / 60);
111
+ const diffDays = Math.floor(diffHours / 24);
112
+ if (diffSecs < 60) return "Just now";
113
+ if (diffMins < 60) return `${diffMins} minute${diffMins > 1 ? "s" : ""} ago`;
114
+ if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? "s" : ""} ago`;
115
+ if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? "s" : ""} ago`;
116
+ return date.toLocaleDateString();
117
+ }
118
+ function truncate(str, maxLength) {
119
+ if (str.length <= maxLength) return str;
120
+ return str.slice(0, maxLength - 1) + "\u2026";
121
+ }
122
+ function maskString(str, showFirst = 4, showLast = 4) {
123
+ if (str.length <= showFirst + showLast) {
124
+ return "*".repeat(str.length);
125
+ }
126
+ const first = str.slice(0, showFirst);
127
+ const last = str.slice(-showLast);
128
+ const masked = "*".repeat(Math.min(8, str.length - showFirst - showLast));
129
+ return `${first}${masked}${last}`;
130
+ }
131
+ function formatDuration(ms) {
132
+ if (ms === void 0) return chalk.dim("\u2014");
133
+ if (ms < 1e3) return `${ms}ms`;
134
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
135
+ return `${(ms / 6e4).toFixed(1)}m`;
136
+ }
137
+ function formatStatus(status) {
138
+ const statusColors = {
139
+ success: chalk.green,
140
+ completed: chalk.green,
141
+ active: chalk.green,
142
+ enabled: chalk.green,
143
+ failed: chalk.red,
144
+ error: chalk.red,
145
+ disabled: chalk.red,
146
+ pending: chalk.yellow,
147
+ running: chalk.blue,
148
+ in_progress: chalk.blue
149
+ };
150
+ const colorFn = statusColors[status.toLowerCase()] ?? chalk.white;
151
+ return colorFn(status);
152
+ }
153
+ function formatDate(dateStr) {
154
+ if (!dateStr) return chalk.dim("\u2014");
155
+ const date = typeof dateStr === "string" ? new Date(dateStr) : dateStr;
156
+ return date.toLocaleDateString("en-US", {
157
+ month: "short",
158
+ day: "numeric",
159
+ year: "numeric",
160
+ hour: "2-digit",
161
+ minute: "2-digit"
162
+ });
163
+ }
164
+ function printSimpleTable(headers, rows) {
165
+ if (isJsonOutput()) {
166
+ const data = rows.map((row) => {
167
+ const obj = {};
168
+ headers.forEach((h, i) => {
169
+ obj[h] = row[i] ?? "";
170
+ });
171
+ return obj;
172
+ });
173
+ printJson(data);
174
+ return;
175
+ }
176
+ if (rows.length === 0) {
177
+ console.log(chalk.dim("No data to display"));
178
+ return;
179
+ }
180
+ const widths = headers.map((header, i) => {
181
+ const maxDataWidth = rows.reduce((max, row) => {
182
+ const value = stripAnsi(row[i] ?? "");
183
+ return Math.max(max, value.length);
184
+ }, 0);
185
+ return Math.max(header.length, maxDataWidth);
186
+ });
187
+ const headerLine = headers.map((h, i) => padString(h, widths[i] ?? 0)).join(" ");
188
+ console.log(chalk.bold(headerLine));
189
+ console.log(
190
+ chalk.dim(
191
+ widths.map((w) => "\u2500".repeat(w)).join("\u2500\u2500")
192
+ )
193
+ );
194
+ for (const row of rows) {
195
+ const rowLine = row.map((cell, i) => padString(cell, widths[i] ?? 0)).join(" ");
196
+ console.log(rowLine);
197
+ }
198
+ }
199
+ export {
200
+ formatBoolean,
201
+ formatDate,
202
+ formatDuration,
203
+ formatRelativeDate,
204
+ formatStatus,
205
+ getOutputOptions,
206
+ isJsonOutput,
207
+ maskString,
208
+ printBlank,
209
+ printError,
210
+ printHeader,
211
+ printInfo,
212
+ printJson,
213
+ printLabel,
214
+ printSimpleTable,
215
+ printSuccess,
216
+ printTable,
217
+ printWarning,
218
+ setOutputOptions,
219
+ truncate
220
+ };
221
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/output.ts"],"sourcesContent":["import chalk from 'chalk';\n\n/**\n * Output formatting options\n */\nexport interface OutputOptions {\n json?: boolean;\n noColor?: boolean;\n}\n\n/**\n * Global output context (set by CLI flags)\n */\nlet globalOptions: OutputOptions = {};\n\n/**\n * Set global output options\n */\nexport function setOutputOptions(options: OutputOptions): void {\n globalOptions = { ...globalOptions, ...options };\n}\n\n/**\n * Get current output options\n */\nexport function getOutputOptions(): OutputOptions {\n return globalOptions;\n}\n\n/**\n * Check if JSON output is enabled\n */\nexport function isJsonOutput(): boolean {\n return globalOptions.json === true;\n}\n\n/**\n * Print JSON output\n */\nexport function printJson(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n}\n\n/**\n * Print success message with checkmark\n */\nexport function printSuccess(message: string): void {\n if (isJsonOutput()) return;\n console.log(chalk.green('✓'), message);\n}\n\n/**\n * Print error message with X mark\n */\nexport function printError(message: string, details?: string): void {\n if (isJsonOutput()) {\n printJson({ error: message, details });\n return;\n }\n console.error(chalk.red('✗'), chalk.red('Error:'), message);\n if (details) {\n console.error(' ', chalk.dim(details));\n }\n}\n\n/**\n * Print warning message\n */\nexport function printWarning(message: string): void {\n if (isJsonOutput()) return;\n console.log(chalk.yellow('!'), chalk.yellow('Warning:'), message);\n}\n\n/**\n * Print info message\n */\nexport function printInfo(message: string): void {\n if (isJsonOutput()) return;\n console.log(chalk.blue('ℹ'), message);\n}\n\n/**\n * Print a labeled value\n */\nexport function printLabel(label: string, value: string | number | boolean): void {\n if (isJsonOutput()) return;\n console.log(chalk.dim(label + ':'), value);\n}\n\n/**\n * Print a header/title\n */\nexport function printHeader(title: string): void {\n if (isJsonOutput()) return;\n console.log();\n console.log(chalk.bold(title));\n console.log(chalk.dim('─'.repeat(title.length)));\n}\n\n/**\n * Print a blank line\n */\nexport function printBlank(): void {\n if (isJsonOutput()) return;\n console.log();\n}\n\n/**\n * Table column definition\n */\nexport interface TableColumn {\n header: string;\n key: string;\n width?: number;\n align?: 'left' | 'right' | 'center';\n format?: (value: unknown) => string;\n}\n\n/**\n * Print a simple table\n */\nexport function printTable<T extends Record<string, unknown>>(\n columns: TableColumn[],\n rows: T[]\n): void {\n if (isJsonOutput()) {\n printJson(rows);\n return;\n }\n\n if (rows.length === 0) {\n console.log(chalk.dim('No data to display'));\n return;\n }\n\n // Calculate column widths\n const widths = columns.map((col) => {\n const headerWidth = col.header.length;\n const maxDataWidth = rows.reduce((max, row) => {\n const value = col.format ? col.format(row[col.key]) : String(row[col.key] ?? '');\n return Math.max(max, value.length);\n }, 0);\n return col.width ?? Math.max(headerWidth, maxDataWidth);\n });\n\n // Print header\n const headerLine = columns\n .map((col, i) => padString(col.header, widths[i] ?? 0, col.align))\n .join(' ');\n console.log(chalk.bold(headerLine));\n\n // Print separator\n console.log(\n chalk.dim(\n widths.map((w) => '─'.repeat(w)).join('──')\n )\n );\n\n // Print rows\n for (const row of rows) {\n const rowLine = columns\n .map((col, i) => {\n const value = col.format ? col.format(row[col.key]) : String(row[col.key] ?? '');\n return padString(value, widths[i] ?? 0, col.align);\n })\n .join(' ');\n console.log(rowLine);\n }\n}\n\n/**\n * Pad string to a fixed width\n */\nfunction padString(str: string, width: number, align: 'left' | 'right' | 'center' = 'left'): string {\n const strLen = stripAnsi(str).length;\n const padding = Math.max(0, width - strLen);\n\n switch (align) {\n case 'right':\n return ' '.repeat(padding) + str;\n case 'center':\n const leftPad = Math.floor(padding / 2);\n const rightPad = padding - leftPad;\n return ' '.repeat(leftPad) + str + ' '.repeat(rightPad);\n default:\n return str + ' '.repeat(padding);\n }\n}\n\n/**\n * Strip ANSI codes from string for accurate length calculation\n */\nfunction stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\x1B\\[[0-9;]*[a-zA-Z]/g, '');\n}\n\n/**\n * Format a boolean as checkmark or X\n */\nexport function formatBoolean(value: unknown): string {\n return value ? chalk.green('✓') : chalk.dim('✗');\n}\n\n/**\n * Format a date relative to now\n */\nexport function formatRelativeDate(dateStr: string | Date | undefined): string {\n if (!dateStr) return chalk.dim('Never');\n\n const date = typeof dateStr === 'string' ? new Date(dateStr) : dateStr;\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffSecs = Math.floor(diffMs / 1000);\n const diffMins = Math.floor(diffSecs / 60);\n const diffHours = Math.floor(diffMins / 60);\n const diffDays = Math.floor(diffHours / 24);\n\n if (diffSecs < 60) return 'Just now';\n if (diffMins < 60) return `${diffMins} minute${diffMins > 1 ? 's' : ''} ago`;\n if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;\n if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;\n\n return date.toLocaleDateString();\n}\n\n/**\n * Truncate string with ellipsis\n */\nexport function truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return str.slice(0, maxLength - 1) + '…';\n}\n\n/**\n * Mask sensitive string (show first and last few characters)\n */\nexport function maskString(str: string, showFirst = 4, showLast = 4): string {\n if (str.length <= showFirst + showLast) {\n return '*'.repeat(str.length);\n }\n const first = str.slice(0, showFirst);\n const last = str.slice(-showLast);\n const masked = '*'.repeat(Math.min(8, str.length - showFirst - showLast));\n return `${first}${masked}${last}`;\n}\n\n/**\n * Format duration in milliseconds\n */\nexport function formatDuration(ms: number | undefined): string {\n if (ms === undefined) return chalk.dim('—');\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n return `${(ms / 60000).toFixed(1)}m`;\n}\n\n/**\n * Format status with color\n */\nexport function formatStatus(status: string): string {\n const statusColors: Record<string, (s: string) => string> = {\n success: chalk.green,\n completed: chalk.green,\n active: chalk.green,\n enabled: chalk.green,\n failed: chalk.red,\n error: chalk.red,\n disabled: chalk.red,\n pending: chalk.yellow,\n running: chalk.blue,\n in_progress: chalk.blue,\n };\n\n const colorFn = statusColors[status.toLowerCase()] ?? chalk.white;\n return colorFn(status);\n}\n\n/**\n * Format a date as a short date string\n */\nexport function formatDate(dateStr: string | Date | undefined): string {\n if (!dateStr) return chalk.dim('—');\n\n const date = typeof dateStr === 'string' ? new Date(dateStr) : dateStr;\n return date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\n/**\n * Print a simple table from header and row arrays\n * Simplified version for string[][] data\n */\nexport function printSimpleTable(headers: string[], rows: string[][]): void {\n if (isJsonOutput()) {\n // Convert to array of objects for JSON output\n const data = rows.map((row) => {\n const obj: Record<string, string> = {};\n headers.forEach((h, i) => {\n obj[h] = row[i] ?? '';\n });\n return obj;\n });\n printJson(data);\n return;\n }\n\n if (rows.length === 0) {\n console.log(chalk.dim('No data to display'));\n return;\n }\n\n // Calculate column widths\n const widths = headers.map((header, i) => {\n const maxDataWidth = rows.reduce((max, row) => {\n const value = stripAnsi(row[i] ?? '');\n return Math.max(max, value.length);\n }, 0);\n return Math.max(header.length, maxDataWidth);\n });\n\n // Print header\n const headerLine = headers\n .map((h, i) => padString(h, widths[i] ?? 0))\n .join(' ');\n console.log(chalk.bold(headerLine));\n\n // Print separator\n console.log(\n chalk.dim(\n widths.map((w) => '─'.repeat(w)).join('──')\n )\n );\n\n // Print rows\n for (const row of rows) {\n const rowLine = row\n .map((cell, i) => padString(cell, widths[i] ?? 0))\n .join(' ');\n console.log(rowLine);\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,15 @@
1
+ import { ChanlSDK } from '@chanl-ai/sdk';
2
+
3
+ /**
4
+ * Create an authenticated SDK instance from stored config.
5
+ * Supports both API key and JWT token auth.
6
+ * Returns null with error message if not authenticated.
7
+ */
8
+ declare function createSdk(): ChanlSDK | null;
9
+ /**
10
+ * Get workspace ID from config, with error message if not set.
11
+ * Returns null with error message if no workspace selected.
12
+ */
13
+ declare function getWorkspaceId(): string | null;
14
+
15
+ export { createSdk, getWorkspaceId };
@@ -0,0 +1,34 @@
1
+ import { ChanlSDK } from "@chanl-ai/sdk";
2
+ import { configStore } from "./config-store.js";
3
+ import { printError } from "./output.js";
4
+ function createSdk() {
5
+ const apiKey = configStore.getApiKey();
6
+ const jwtToken = configStore.getJwtToken();
7
+ const baseUrl = configStore.getBaseUrl();
8
+ if (!apiKey && !jwtToken) {
9
+ printError("Not authenticated", "Run 'chanl login' to authenticate");
10
+ process.exitCode = 1;
11
+ return null;
12
+ }
13
+ if (apiKey) {
14
+ if (apiKey.startsWith("eyJ")) {
15
+ return new ChanlSDK({ jwtToken: apiKey, baseUrl });
16
+ }
17
+ return new ChanlSDK({ apiKey, baseUrl });
18
+ }
19
+ return new ChanlSDK({ jwtToken, baseUrl });
20
+ }
21
+ function getWorkspaceId() {
22
+ const workspaceId = configStore.getWorkspaceId();
23
+ if (!workspaceId) {
24
+ printError("No workspace selected", "Run 'chanl config set workspaceId <id>' to select a workspace");
25
+ process.exitCode = 1;
26
+ return null;
27
+ }
28
+ return workspaceId;
29
+ }
30
+ export {
31
+ createSdk,
32
+ getWorkspaceId
33
+ };
34
+ //# sourceMappingURL=sdk-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/sdk-factory.ts"],"sourcesContent":["import { ChanlSDK } from '@chanl-ai/sdk';\nimport { configStore } from './config-store.js';\nimport { printError } from './output.js';\n\n/**\n * Create an authenticated SDK instance from stored config.\n * Supports both API key and JWT token auth.\n * Returns null with error message if not authenticated.\n */\nexport function createSdk(): ChanlSDK | null {\n const apiKey = configStore.getApiKey();\n const jwtToken = configStore.getJwtToken();\n const baseUrl = configStore.getBaseUrl();\n\n if (!apiKey && !jwtToken) {\n printError('Not authenticated', \"Run 'chanl login' to authenticate\");\n process.exitCode = 1;\n return null;\n }\n\n if (apiKey) {\n // API key might be a JWT (legacy compat)\n if (apiKey.startsWith('eyJ')) {\n return new ChanlSDK({ jwtToken: apiKey, baseUrl });\n }\n return new ChanlSDK({ apiKey, baseUrl });\n }\n\n return new ChanlSDK({ jwtToken: jwtToken!, baseUrl });\n}\n\n/**\n * Get workspace ID from config, with error message if not set.\n * Returns null with error message if no workspace selected.\n */\nexport function getWorkspaceId(): string | null {\n const workspaceId = configStore.getWorkspaceId();\n\n if (!workspaceId) {\n printError('No workspace selected', \"Run 'chanl config set workspaceId <id>' to select a workspace\");\n process.exitCode = 1;\n return null;\n }\n\n return workspaceId;\n}\n"],"mappings":"AAAA,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAOpB,SAAS,YAA6B;AAC3C,QAAM,SAAS,YAAY,UAAU;AACrC,QAAM,WAAW,YAAY,YAAY;AACzC,QAAM,UAAU,YAAY,WAAW;AAEvC,MAAI,CAAC,UAAU,CAAC,UAAU;AACxB,eAAW,qBAAqB,mCAAmC;AACnE,YAAQ,WAAW;AACnB,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ;AAEV,QAAI,OAAO,WAAW,KAAK,GAAG;AAC5B,aAAO,IAAI,SAAS,EAAE,UAAU,QAAQ,QAAQ,CAAC;AAAA,IACnD;AACA,WAAO,IAAI,SAAS,EAAE,QAAQ,QAAQ,CAAC;AAAA,EACzC;AAEA,SAAO,IAAI,SAAS,EAAE,UAAqB,QAAQ,CAAC;AACtD;AAMO,SAAS,iBAAgC;AAC9C,QAAM,cAAc,YAAY,eAAe;AAE/C,MAAI,CAAC,aAAa;AAChB,eAAW,yBAAyB,+DAA+D;AACnG,YAAQ,WAAW;AACnB,WAAO;AAAA,EACT;AAEA,SAAO;AACT;","names":[]}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@chanl-ai/cli",
3
+ "version": "2.0.1",
4
+ "description": "Command-line interface for Chanl Analytics",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "bin": {
8
+ "chanl": "./bin/chanl.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsup",
12
+ "dev": "tsup --watch",
13
+ "clean": "rimraf dist",
14
+ "prebuild": "npm run clean",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest",
17
+ "lint": "eslint src/**/*.ts",
18
+ "format": "prettier --write src/**/*.ts",
19
+ "typecheck": "tsc --noEmit"
20
+ },
21
+ "keywords": [
22
+ "chanl",
23
+ "cli",
24
+ "analytics",
25
+ "api",
26
+ "command-line"
27
+ ],
28
+ "author": "Chanl Analytics",
29
+ "license": "MIT",
30
+ "dependencies": {
31
+ "@chanl-ai/sdk": "*",
32
+ "@inquirer/prompts": "^7.10.1",
33
+ "@modelcontextprotocol/sdk": "^1.25.1",
34
+ "chalk": "^5.3.0",
35
+ "commander": "^12.1.0",
36
+ "conf": "^13.0.1",
37
+ "inquirer": "^12.2.0",
38
+ "open": "^11.0.0",
39
+ "ora": "^8.1.1"
40
+ },
41
+ "devDependencies": {
42
+ "@types/inquirer": "^9.0.7",
43
+ "@types/node": "^22.10.2",
44
+ "rimraf": "^6.0.1",
45
+ "tsup": "^8.3.5",
46
+ "typescript": "^5.7.2",
47
+ "vitest": "^2.1.8"
48
+ },
49
+ "files": [
50
+ "dist"
51
+ ],
52
+ "engines": {
53
+ "node": ">=18.0.0"
54
+ },
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "https://github.com/chanl-ai/chanl-cli.git"
58
+ },
59
+ "bugs": {
60
+ "url": "https://github.com/chanl-ai/chanl-cli/issues"
61
+ },
62
+ "homepage": "https://github.com/chanl-ai/chanl-cli#readme",
63
+ "publishConfig": {
64
+ "registry": "https://registry.npmjs.org",
65
+ "access": "public"
66
+ }
67
+ }