@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.
- package/bin/chanl.js +10 -0
- package/dist/__tests__/cli.test.d.ts +2 -0
- package/dist/__tests__/cli.test.js +2313 -0
- package/dist/__tests__/cli.test.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.js +72 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/agents.d.ts +8 -0
- package/dist/commands/agents.js +671 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/auth.d.ts +16 -0
- package/dist/commands/auth.js +294 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/call.d.ts +8 -0
- package/dist/commands/call.js +166 -0
- package/dist/commands/call.js.map +1 -0
- package/dist/commands/calls.d.ts +8 -0
- package/dist/commands/calls.js +719 -0
- package/dist/commands/calls.js.map +1 -0
- package/dist/commands/chat.d.ts +8 -0
- package/dist/commands/chat.js +203 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/config.d.ts +8 -0
- package/dist/commands/config.js +231 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/health.d.ts +8 -0
- package/dist/commands/health.js +55 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/index.d.ts +18 -0
- package/dist/commands/index.js +39 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/knowledge.d.ts +8 -0
- package/dist/commands/knowledge.js +539 -0
- package/dist/commands/knowledge.js.map +1 -0
- package/dist/commands/mcp.d.ts +8 -0
- package/dist/commands/mcp.js +589 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/memory.d.ts +8 -0
- package/dist/commands/memory.js +408 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/personas.d.ts +8 -0
- package/dist/commands/personas.js +356 -0
- package/dist/commands/personas.js.map +1 -0
- package/dist/commands/prompts.d.ts +8 -0
- package/dist/commands/prompts.js +295 -0
- package/dist/commands/prompts.js.map +1 -0
- package/dist/commands/scenarios.d.ts +8 -0
- package/dist/commands/scenarios.js +591 -0
- package/dist/commands/scenarios.js.map +1 -0
- package/dist/commands/scorecards.d.ts +8 -0
- package/dist/commands/scorecards.js +570 -0
- package/dist/commands/scorecards.js.map +1 -0
- package/dist/commands/tools.d.ts +8 -0
- package/dist/commands/tools.js +632 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/toolsets.d.ts +8 -0
- package/dist/commands/toolsets.js +464 -0
- package/dist/commands/toolsets.js.map +1 -0
- package/dist/commands/workspaces.d.ts +8 -0
- package/dist/commands/workspaces.js +170 -0
- package/dist/commands/workspaces.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/config-store.d.ts +117 -0
- package/dist/utils/config-store.js +191 -0
- package/dist/utils/config-store.js.map +1 -0
- package/dist/utils/interactive.d.ts +41 -0
- package/dist/utils/interactive.js +83 -0
- package/dist/utils/interactive.js.map +1 -0
- package/dist/utils/output.d.ts +100 -0
- package/dist/utils/output.js +221 -0
- package/dist/utils/output.js.map +1 -0
- package/dist/utils/sdk-factory.d.ts +15 -0
- package/dist/utils/sdk-factory.js +34 -0
- package/dist/utils/sdk-factory.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { createSdk } from "../utils/sdk-factory.js";
|
|
5
|
+
import { configStore } from "../utils/config-store.js";
|
|
6
|
+
import {
|
|
7
|
+
printError,
|
|
8
|
+
printSuccess,
|
|
9
|
+
printInfo,
|
|
10
|
+
printBlank,
|
|
11
|
+
printSimpleTable,
|
|
12
|
+
printLabel,
|
|
13
|
+
isJsonOutput,
|
|
14
|
+
printJson,
|
|
15
|
+
formatDate
|
|
16
|
+
} from "../utils/output.js";
|
|
17
|
+
function createWorkspacesCommand() {
|
|
18
|
+
const workspaces = new Command("workspaces").description("Manage workspaces").addHelpText(
|
|
19
|
+
"after",
|
|
20
|
+
`
|
|
21
|
+
What are Workspaces?
|
|
22
|
+
Workspaces are isolated environments for organizing agents, tools, and
|
|
23
|
+
configurations. Switch between workspaces to manage different projects.
|
|
24
|
+
|
|
25
|
+
Quick Start:
|
|
26
|
+
$ chanl workspaces list # List your workspaces
|
|
27
|
+
$ chanl workspaces get <id> # View workspace details
|
|
28
|
+
$ chanl workspaces use <id> # Set active workspace`
|
|
29
|
+
);
|
|
30
|
+
workspaces.command("list").description("List workspaces").addHelpText(
|
|
31
|
+
"after",
|
|
32
|
+
`
|
|
33
|
+
Examples:
|
|
34
|
+
$ chanl workspaces list # List all workspaces
|
|
35
|
+
$ chanl workspaces list --json # Output as JSON`
|
|
36
|
+
).action(handleWorkspacesList);
|
|
37
|
+
workspaces.command("get <id>").description("Get workspace details").addHelpText(
|
|
38
|
+
"after",
|
|
39
|
+
`
|
|
40
|
+
Examples:
|
|
41
|
+
$ chanl workspaces get ws_abc123 # Get workspace details
|
|
42
|
+
$ chanl workspaces get ws_abc123 --json # Output as JSON`
|
|
43
|
+
).action(handleWorkspacesGet);
|
|
44
|
+
workspaces.command("use <id>").description("Set active workspace (saves to config)").addHelpText(
|
|
45
|
+
"after",
|
|
46
|
+
`
|
|
47
|
+
Examples:
|
|
48
|
+
$ chanl workspaces use ws_abc123 # Switch to workspace
|
|
49
|
+
|
|
50
|
+
This saves the workspace ID to your CLI config. All subsequent commands
|
|
51
|
+
will use this workspace by default.`
|
|
52
|
+
).action(handleWorkspacesUse);
|
|
53
|
+
return workspaces;
|
|
54
|
+
}
|
|
55
|
+
async function handleWorkspacesList() {
|
|
56
|
+
const sdk = createSdk();
|
|
57
|
+
if (!sdk) return;
|
|
58
|
+
const spinner = ora("Fetching workspaces...").start();
|
|
59
|
+
try {
|
|
60
|
+
const response = await sdk.workspace.getAll();
|
|
61
|
+
spinner.stop();
|
|
62
|
+
if (!response.success || !response.data) {
|
|
63
|
+
printError("Failed to fetch workspaces", response.message);
|
|
64
|
+
process.exitCode = 1;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const workspaces = Array.isArray(response.data) ? response.data : [];
|
|
68
|
+
const currentWorkspaceId = configStore.getWorkspaceId();
|
|
69
|
+
if (isJsonOutput()) {
|
|
70
|
+
printJson(workspaces);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (workspaces.length === 0) {
|
|
74
|
+
printInfo("No workspaces found");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
printBlank();
|
|
78
|
+
printSimpleTable(
|
|
79
|
+
["", "ID", "Name", "Description", "Created"],
|
|
80
|
+
workspaces.map((ws) => [
|
|
81
|
+
ws.id === currentWorkspaceId ? chalk.green("*") : " ",
|
|
82
|
+
ws.id,
|
|
83
|
+
(ws.name || "Untitled").slice(0, 30),
|
|
84
|
+
(ws.description || "-").slice(0, 40),
|
|
85
|
+
formatDate(ws.createdAt)
|
|
86
|
+
])
|
|
87
|
+
);
|
|
88
|
+
printBlank();
|
|
89
|
+
if (currentWorkspaceId) {
|
|
90
|
+
printInfo(`Active workspace: ${currentWorkspaceId}`);
|
|
91
|
+
}
|
|
92
|
+
printInfo(`Total: ${workspaces.length} workspaces`);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
spinner.fail("Failed to fetch workspaces");
|
|
95
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
96
|
+
printError("Error", message);
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function handleWorkspacesGet(id) {
|
|
101
|
+
const sdk = createSdk();
|
|
102
|
+
if (!sdk) return;
|
|
103
|
+
const spinner = ora("Fetching workspace...").start();
|
|
104
|
+
try {
|
|
105
|
+
const response = await sdk.workspace.getById(id);
|
|
106
|
+
spinner.stop();
|
|
107
|
+
if (!response.success || !response.data) {
|
|
108
|
+
printError("Failed to fetch workspace", response.message);
|
|
109
|
+
process.exitCode = 1;
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const workspace = response.data;
|
|
113
|
+
if (isJsonOutput()) {
|
|
114
|
+
printJson(workspace);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
printBlank();
|
|
118
|
+
console.log(chalk.bold("Workspace Details:"));
|
|
119
|
+
printLabel("ID", workspace.id);
|
|
120
|
+
printLabel("Name", workspace.name);
|
|
121
|
+
if (workspace.description) printLabel("Description", workspace.description);
|
|
122
|
+
if (workspace.createdAt) printLabel("Created", formatDate(workspace.createdAt));
|
|
123
|
+
if (workspace.updatedAt) printLabel("Updated", formatDate(workspace.updatedAt));
|
|
124
|
+
const currentWorkspaceId = configStore.getWorkspaceId();
|
|
125
|
+
if (workspace.id === currentWorkspaceId) {
|
|
126
|
+
printBlank();
|
|
127
|
+
printInfo("This is your active workspace");
|
|
128
|
+
}
|
|
129
|
+
printBlank();
|
|
130
|
+
} catch (error) {
|
|
131
|
+
spinner.fail("Failed to fetch workspace");
|
|
132
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
133
|
+
printError("Error", message);
|
|
134
|
+
process.exitCode = 1;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async function handleWorkspacesUse(id) {
|
|
138
|
+
const sdk = createSdk();
|
|
139
|
+
if (!sdk) return;
|
|
140
|
+
const spinner = ora("Verifying workspace...").start();
|
|
141
|
+
try {
|
|
142
|
+
const response = await sdk.workspace.getById(id);
|
|
143
|
+
spinner.stop();
|
|
144
|
+
if (!response.success || !response.data) {
|
|
145
|
+
printError("Workspace not found", response.message || `Could not find workspace: ${id}`);
|
|
146
|
+
process.exitCode = 1;
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const workspace = response.data;
|
|
150
|
+
configStore.setWorkspaceId(id);
|
|
151
|
+
if (isJsonOutput()) {
|
|
152
|
+
printJson({
|
|
153
|
+
success: true,
|
|
154
|
+
workspaceId: id,
|
|
155
|
+
name: workspace.name
|
|
156
|
+
});
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
printSuccess(`Active workspace set to: ${workspace.name} (${id})`);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
spinner.fail("Failed to set workspace");
|
|
162
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
163
|
+
printError("Error", message);
|
|
164
|
+
process.exitCode = 1;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
export {
|
|
168
|
+
createWorkspacesCommand
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=workspaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/workspaces.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport { configStore } from '../utils/config-store.js';\nimport {\n printError,\n printSuccess,\n printInfo,\n printBlank,\n printSimpleTable,\n printLabel,\n isJsonOutput,\n printJson,\n formatDate,\n} from '../utils/output.js';\n\n/**\n * Create the workspaces command group\n */\nexport function createWorkspacesCommand(): Command {\n const workspaces = new Command('workspaces')\n .description('Manage workspaces')\n .addHelpText(\n 'after',\n `\nWhat are Workspaces?\n Workspaces are isolated environments for organizing agents, tools, and\n configurations. Switch between workspaces to manage different projects.\n\nQuick Start:\n $ chanl workspaces list # List your workspaces\n $ chanl workspaces get <id> # View workspace details\n $ chanl workspaces use <id> # Set active workspace`\n );\n\n // workspaces list\n workspaces\n .command('list')\n .description('List workspaces')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl workspaces list # List all workspaces\n $ chanl workspaces list --json # Output as JSON`\n )\n .action(handleWorkspacesList);\n\n // workspaces get <id>\n workspaces\n .command('get <id>')\n .description('Get workspace details')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl workspaces get ws_abc123 # Get workspace details\n $ chanl workspaces get ws_abc123 --json # Output as JSON`\n )\n .action(handleWorkspacesGet);\n\n // workspaces use <id>\n workspaces\n .command('use <id>')\n .description('Set active workspace (saves to config)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl workspaces use ws_abc123 # Switch to workspace\n\nThis saves the workspace ID to your CLI config. All subsequent commands\nwill use this workspace by default.`\n )\n .action(handleWorkspacesUse);\n\n return workspaces;\n}\n\n/**\n * Handle workspaces list command\n */\nasync function handleWorkspacesList(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching workspaces...').start();\n\n try {\n const response = await sdk.workspace.getAll();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch workspaces', response.message);\n process.exitCode = 1;\n return;\n }\n\n const workspaces = Array.isArray(response.data) ? response.data : [];\n const currentWorkspaceId = configStore.getWorkspaceId();\n\n if (isJsonOutput()) {\n printJson(workspaces);\n return;\n }\n\n if (workspaces.length === 0) {\n printInfo('No workspaces found');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['', 'ID', 'Name', 'Description', 'Created'],\n workspaces.map((ws: any) => [\n ws.id === currentWorkspaceId ? chalk.green('*') : ' ',\n ws.id,\n (ws.name || 'Untitled').slice(0, 30),\n (ws.description || '-').slice(0, 40),\n formatDate(ws.createdAt),\n ])\n );\n\n printBlank();\n if (currentWorkspaceId) {\n printInfo(`Active workspace: ${currentWorkspaceId}`);\n }\n printInfo(`Total: ${workspaces.length} workspaces`);\n } catch (error) {\n spinner.fail('Failed to fetch workspaces');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle workspaces get command\n */\nasync function handleWorkspacesGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching workspace...').start();\n\n try {\n const response = await sdk.workspace.getById(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch workspace', response.message);\n process.exitCode = 1;\n return;\n }\n\n const workspace = response.data;\n\n if (isJsonOutput()) {\n printJson(workspace);\n return;\n }\n\n printBlank();\n console.log(chalk.bold('Workspace Details:'));\n printLabel('ID', workspace.id);\n printLabel('Name', workspace.name);\n if (workspace.description) printLabel('Description', workspace.description);\n if (workspace.createdAt) printLabel('Created', formatDate(workspace.createdAt));\n if (workspace.updatedAt) printLabel('Updated', formatDate(workspace.updatedAt));\n\n const currentWorkspaceId = configStore.getWorkspaceId();\n if (workspace.id === currentWorkspaceId) {\n printBlank();\n printInfo('This is your active workspace');\n }\n\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch workspace');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle workspaces use command\n */\nasync function handleWorkspacesUse(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Verifying workspace...').start();\n\n try {\n // Verify the workspace exists before saving\n const response = await sdk.workspace.getById(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Workspace not found', response.message || `Could not find workspace: ${id}`);\n process.exitCode = 1;\n return;\n }\n\n const workspace = response.data;\n\n // Save to config\n configStore.setWorkspaceId(id);\n\n if (isJsonOutput()) {\n printJson({\n success: true,\n workspaceId: id,\n name: workspace.name,\n });\n return;\n }\n\n printSuccess(`Active workspace set to: ${workspace.name} (${id})`);\n } catch (error) {\n spinner.fail('Failed to set workspace');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @chanl-ai/cli - Command-line interface for Chanl\n *\n * Entry point for the CLI application.\n */\n\nimport { run } from './cli.js';\n\n// Run the CLI\nrun().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n"],"mappings":"AAMA,SAAS,WAAW;AAGpB,IAAI,EAAE,MAAM,CAAC,UAAU;AACrB,UAAQ,MAAM,gBAAgB,KAAK;AACnC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI configuration schema
|
|
3
|
+
*/
|
|
4
|
+
interface ChanlCliConfig {
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
jwtToken?: string;
|
|
7
|
+
refreshToken?: string;
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
workspaceId?: string;
|
|
10
|
+
appUrl?: string;
|
|
11
|
+
defaultFormat: 'table' | 'json';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Get the Chanl config directory path
|
|
15
|
+
* Uses ~/.chanl/ for storing configuration
|
|
16
|
+
*/
|
|
17
|
+
declare function getConfigDir(): string;
|
|
18
|
+
/**
|
|
19
|
+
* Config store using Conf library
|
|
20
|
+
* Stores configuration in ~/.chanl/config.json
|
|
21
|
+
*/
|
|
22
|
+
declare class ConfigStore {
|
|
23
|
+
private store;
|
|
24
|
+
constructor();
|
|
25
|
+
/**
|
|
26
|
+
* Get a configuration value
|
|
27
|
+
* Supports dot notation for nested values
|
|
28
|
+
*/
|
|
29
|
+
get<K extends keyof ChanlCliConfig>(key: K): ChanlCliConfig[K];
|
|
30
|
+
/**
|
|
31
|
+
* Set a configuration value
|
|
32
|
+
*/
|
|
33
|
+
set<K extends keyof ChanlCliConfig>(key: K, value: ChanlCliConfig[K]): void;
|
|
34
|
+
/**
|
|
35
|
+
* Delete a configuration value
|
|
36
|
+
*/
|
|
37
|
+
delete(key: keyof ChanlCliConfig): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get all configuration values
|
|
40
|
+
*/
|
|
41
|
+
getAll(): ChanlCliConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Check if a key exists in the configuration
|
|
44
|
+
*/
|
|
45
|
+
has(key: keyof ChanlCliConfig): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Clear all configuration
|
|
48
|
+
*/
|
|
49
|
+
clear(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Get the path to the config file
|
|
52
|
+
*/
|
|
53
|
+
getPath(): string;
|
|
54
|
+
/**
|
|
55
|
+
* Get API key with environment variable fallback
|
|
56
|
+
* Priority: CHANL_API_KEY env var > config file
|
|
57
|
+
*/
|
|
58
|
+
getApiKey(): string | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Get JWT token from config
|
|
61
|
+
*/
|
|
62
|
+
getJwtToken(): string | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Get refresh token from config
|
|
65
|
+
*/
|
|
66
|
+
getRefreshToken(): string | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Get base URL with environment variable fallback
|
|
69
|
+
* Priority: CHANL_BASE_URL env var > config file > default
|
|
70
|
+
*/
|
|
71
|
+
getBaseUrl(): string;
|
|
72
|
+
/**
|
|
73
|
+
* Get the app URL for browser-based flows (e.g., CLI auth)
|
|
74
|
+
* Priority: CHANL_APP_URL env var > config file > derived from baseUrl
|
|
75
|
+
*/
|
|
76
|
+
getAppUrl(): string;
|
|
77
|
+
/**
|
|
78
|
+
* Get workspace ID with environment variable fallback
|
|
79
|
+
* Priority: CHANL_WORKSPACE_ID env var > config file
|
|
80
|
+
*/
|
|
81
|
+
getWorkspaceId(): string | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Check if user is authenticated (has API key or JWT token)
|
|
84
|
+
*/
|
|
85
|
+
isAuthenticated(): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Get the auth method in use
|
|
88
|
+
*/
|
|
89
|
+
getAuthMethod(): 'api-key' | 'jwt' | null;
|
|
90
|
+
/**
|
|
91
|
+
* Set API key in config
|
|
92
|
+
*/
|
|
93
|
+
setApiKey(apiKey: string): void;
|
|
94
|
+
/**
|
|
95
|
+
* Set JWT tokens in config (from browser login)
|
|
96
|
+
*/
|
|
97
|
+
setJwtAuth(jwtToken: string, refreshToken: string): void;
|
|
98
|
+
/**
|
|
99
|
+
* Remove all auth credentials from config (logout)
|
|
100
|
+
*/
|
|
101
|
+
clearAuth(): void;
|
|
102
|
+
/**
|
|
103
|
+
* Remove API key from config (logout)
|
|
104
|
+
*/
|
|
105
|
+
removeApiKey(): void;
|
|
106
|
+
/**
|
|
107
|
+
* Set workspace ID in config
|
|
108
|
+
*/
|
|
109
|
+
setWorkspaceId(workspaceId: string): void;
|
|
110
|
+
/**
|
|
111
|
+
* Set base URL in config
|
|
112
|
+
*/
|
|
113
|
+
setBaseUrl(baseUrl: string): void;
|
|
114
|
+
}
|
|
115
|
+
declare const configStore: ConfigStore;
|
|
116
|
+
|
|
117
|
+
export { type ChanlCliConfig, ConfigStore, configStore, getConfigDir };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import Conf from "conf";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
5
|
+
const DEFAULT_CONFIG = {
|
|
6
|
+
baseUrl: "https://platform.chanl.ai",
|
|
7
|
+
defaultFormat: "table"
|
|
8
|
+
};
|
|
9
|
+
function getConfigDir() {
|
|
10
|
+
return join(homedir(), ".chanl");
|
|
11
|
+
}
|
|
12
|
+
function ensureConfigDir() {
|
|
13
|
+
const configDir = getConfigDir();
|
|
14
|
+
if (!existsSync(configDir)) {
|
|
15
|
+
mkdirSync(configDir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
class ConfigStore {
|
|
19
|
+
store;
|
|
20
|
+
constructor() {
|
|
21
|
+
ensureConfigDir();
|
|
22
|
+
this.store = new Conf({
|
|
23
|
+
projectName: "chanl",
|
|
24
|
+
cwd: getConfigDir(),
|
|
25
|
+
configName: "config",
|
|
26
|
+
defaults: DEFAULT_CONFIG,
|
|
27
|
+
schema: {
|
|
28
|
+
apiKey: { type: "string" },
|
|
29
|
+
jwtToken: { type: "string" },
|
|
30
|
+
refreshToken: { type: "string" },
|
|
31
|
+
baseUrl: { type: "string", default: DEFAULT_CONFIG.baseUrl },
|
|
32
|
+
workspaceId: { type: "string" },
|
|
33
|
+
appUrl: { type: "string" },
|
|
34
|
+
defaultFormat: {
|
|
35
|
+
type: "string",
|
|
36
|
+
enum: ["table", "json"],
|
|
37
|
+
default: "table"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get a configuration value
|
|
44
|
+
* Supports dot notation for nested values
|
|
45
|
+
*/
|
|
46
|
+
get(key) {
|
|
47
|
+
return this.store.get(key);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Set a configuration value
|
|
51
|
+
*/
|
|
52
|
+
set(key, value) {
|
|
53
|
+
this.store.set(key, value);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Delete a configuration value
|
|
57
|
+
*/
|
|
58
|
+
delete(key) {
|
|
59
|
+
this.store.delete(key);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get all configuration values
|
|
63
|
+
*/
|
|
64
|
+
getAll() {
|
|
65
|
+
return this.store.store;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Check if a key exists in the configuration
|
|
69
|
+
*/
|
|
70
|
+
has(key) {
|
|
71
|
+
return this.store.has(key);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Clear all configuration
|
|
75
|
+
*/
|
|
76
|
+
clear() {
|
|
77
|
+
this.store.clear();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get the path to the config file
|
|
81
|
+
*/
|
|
82
|
+
getPath() {
|
|
83
|
+
return this.store.path;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get API key with environment variable fallback
|
|
87
|
+
* Priority: CHANL_API_KEY env var > config file
|
|
88
|
+
*/
|
|
89
|
+
getApiKey() {
|
|
90
|
+
return process.env["CHANL_API_KEY"] || this.get("apiKey");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get JWT token from config
|
|
94
|
+
*/
|
|
95
|
+
getJwtToken() {
|
|
96
|
+
return this.get("jwtToken");
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get refresh token from config
|
|
100
|
+
*/
|
|
101
|
+
getRefreshToken() {
|
|
102
|
+
return this.get("refreshToken");
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get base URL with environment variable fallback
|
|
106
|
+
* Priority: CHANL_BASE_URL env var > config file > default
|
|
107
|
+
*/
|
|
108
|
+
getBaseUrl() {
|
|
109
|
+
return process.env["CHANL_BASE_URL"] || this.get("baseUrl");
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get the app URL for browser-based flows (e.g., CLI auth)
|
|
113
|
+
* Priority: CHANL_APP_URL env var > config file > derived from baseUrl
|
|
114
|
+
*/
|
|
115
|
+
getAppUrl() {
|
|
116
|
+
if (process.env["CHANL_APP_URL"]) return process.env["CHANL_APP_URL"];
|
|
117
|
+
const stored = this.get("appUrl");
|
|
118
|
+
if (stored) return stored;
|
|
119
|
+
const baseUrl = this.getBaseUrl();
|
|
120
|
+
if (baseUrl.includes("localhost")) return "http://localhost:3001";
|
|
121
|
+
return "https://app.chanl.ai";
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get workspace ID with environment variable fallback
|
|
125
|
+
* Priority: CHANL_WORKSPACE_ID env var > config file
|
|
126
|
+
*/
|
|
127
|
+
getWorkspaceId() {
|
|
128
|
+
return process.env["CHANL_WORKSPACE_ID"] || this.get("workspaceId");
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Check if user is authenticated (has API key or JWT token)
|
|
132
|
+
*/
|
|
133
|
+
isAuthenticated() {
|
|
134
|
+
return !!(this.getApiKey() || this.getJwtToken());
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get the auth method in use
|
|
138
|
+
*/
|
|
139
|
+
getAuthMethod() {
|
|
140
|
+
if (this.getApiKey()) return "api-key";
|
|
141
|
+
if (this.getJwtToken()) return "jwt";
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Set API key in config
|
|
146
|
+
*/
|
|
147
|
+
setApiKey(apiKey) {
|
|
148
|
+
this.set("apiKey", apiKey);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Set JWT tokens in config (from browser login)
|
|
152
|
+
*/
|
|
153
|
+
setJwtAuth(jwtToken, refreshToken) {
|
|
154
|
+
this.set("jwtToken", jwtToken);
|
|
155
|
+
this.set("refreshToken", refreshToken);
|
|
156
|
+
this.delete("apiKey");
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Remove all auth credentials from config (logout)
|
|
160
|
+
*/
|
|
161
|
+
clearAuth() {
|
|
162
|
+
this.delete("apiKey");
|
|
163
|
+
this.delete("jwtToken");
|
|
164
|
+
this.delete("refreshToken");
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Remove API key from config (logout)
|
|
168
|
+
*/
|
|
169
|
+
removeApiKey() {
|
|
170
|
+
this.delete("apiKey");
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Set workspace ID in config
|
|
174
|
+
*/
|
|
175
|
+
setWorkspaceId(workspaceId) {
|
|
176
|
+
this.set("workspaceId", workspaceId);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Set base URL in config
|
|
180
|
+
*/
|
|
181
|
+
setBaseUrl(baseUrl) {
|
|
182
|
+
this.set("baseUrl", baseUrl);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const configStore = new ConfigStore();
|
|
186
|
+
export {
|
|
187
|
+
ConfigStore,
|
|
188
|
+
configStore,
|
|
189
|
+
getConfigDir
|
|
190
|
+
};
|
|
191
|
+
//# sourceMappingURL=config-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/config-store.ts"],"sourcesContent":["import Conf from 'conf';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { existsSync, mkdirSync } from 'node:fs';\n\n/**\n * CLI configuration schema\n */\nexport interface ChanlCliConfig {\n apiKey?: string;\n jwtToken?: string;\n refreshToken?: string;\n baseUrl: string;\n workspaceId?: string;\n appUrl?: string;\n defaultFormat: 'table' | 'json';\n}\n\n/**\n * Default configuration values\n */\nconst DEFAULT_CONFIG: ChanlCliConfig = {\n baseUrl: 'https://platform.chanl.ai',\n defaultFormat: 'table',\n};\n\n/**\n * Get the Chanl config directory path\n * Uses ~/.chanl/ for storing configuration\n */\nexport function getConfigDir(): string {\n return join(homedir(), '.chanl');\n}\n\n/**\n * Ensure the config directory exists\n */\nfunction ensureConfigDir(): void {\n const configDir = getConfigDir();\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n}\n\n/**\n * Config store using Conf library\n * Stores configuration in ~/.chanl/config.json\n */\nclass ConfigStore {\n private store: Conf<ChanlCliConfig>;\n\n constructor() {\n ensureConfigDir();\n this.store = new Conf<ChanlCliConfig>({\n projectName: 'chanl',\n cwd: getConfigDir(),\n configName: 'config',\n defaults: DEFAULT_CONFIG,\n schema: {\n apiKey: { type: 'string' },\n jwtToken: { type: 'string' },\n refreshToken: { type: 'string' },\n baseUrl: { type: 'string', default: DEFAULT_CONFIG.baseUrl },\n workspaceId: { type: 'string' },\n appUrl: { type: 'string' },\n defaultFormat: {\n type: 'string',\n enum: ['table', 'json'],\n default: 'table',\n },\n },\n });\n }\n\n /**\n * Get a configuration value\n * Supports dot notation for nested values\n */\n get<K extends keyof ChanlCliConfig>(key: K): ChanlCliConfig[K] {\n return this.store.get(key);\n }\n\n /**\n * Set a configuration value\n */\n set<K extends keyof ChanlCliConfig>(key: K, value: ChanlCliConfig[K]): void {\n this.store.set(key, value);\n }\n\n /**\n * Delete a configuration value\n */\n delete(key: keyof ChanlCliConfig): void {\n this.store.delete(key);\n }\n\n /**\n * Get all configuration values\n */\n getAll(): ChanlCliConfig {\n return this.store.store;\n }\n\n /**\n * Check if a key exists in the configuration\n */\n has(key: keyof ChanlCliConfig): boolean {\n return this.store.has(key);\n }\n\n /**\n * Clear all configuration\n */\n clear(): void {\n this.store.clear();\n }\n\n /**\n * Get the path to the config file\n */\n getPath(): string {\n return this.store.path;\n }\n\n /**\n * Get API key with environment variable fallback\n * Priority: CHANL_API_KEY env var > config file\n */\n getApiKey(): string | undefined {\n return process.env['CHANL_API_KEY'] || this.get('apiKey');\n }\n\n /**\n * Get JWT token from config\n */\n getJwtToken(): string | undefined {\n return this.get('jwtToken');\n }\n\n /**\n * Get refresh token from config\n */\n getRefreshToken(): string | undefined {\n return this.get('refreshToken');\n }\n\n /**\n * Get base URL with environment variable fallback\n * Priority: CHANL_BASE_URL env var > config file > default\n */\n getBaseUrl(): string {\n return process.env['CHANL_BASE_URL'] || this.get('baseUrl');\n }\n\n /**\n * Get the app URL for browser-based flows (e.g., CLI auth)\n * Priority: CHANL_APP_URL env var > config file > derived from baseUrl\n */\n getAppUrl(): string {\n if (process.env['CHANL_APP_URL']) return process.env['CHANL_APP_URL'];\n const stored = this.get('appUrl');\n if (stored) return stored;\n\n // Derive from baseUrl — localhost auto-maps to local frontend\n const baseUrl = this.getBaseUrl();\n if (baseUrl.includes('localhost')) return 'http://localhost:3001';\n return 'https://app.chanl.ai';\n }\n\n /**\n * Get workspace ID with environment variable fallback\n * Priority: CHANL_WORKSPACE_ID env var > config file\n */\n getWorkspaceId(): string | undefined {\n return process.env['CHANL_WORKSPACE_ID'] || this.get('workspaceId');\n }\n\n /**\n * Check if user is authenticated (has API key or JWT token)\n */\n isAuthenticated(): boolean {\n return !!(this.getApiKey() || this.getJwtToken());\n }\n\n /**\n * Get the auth method in use\n */\n getAuthMethod(): 'api-key' | 'jwt' | null {\n if (this.getApiKey()) return 'api-key';\n if (this.getJwtToken()) return 'jwt';\n return null;\n }\n\n /**\n * Set API key in config\n */\n setApiKey(apiKey: string): void {\n this.set('apiKey', apiKey);\n }\n\n /**\n * Set JWT tokens in config (from browser login)\n */\n setJwtAuth(jwtToken: string, refreshToken: string): void {\n this.set('jwtToken', jwtToken);\n this.set('refreshToken', refreshToken);\n // Clear API key if switching to JWT auth\n this.delete('apiKey');\n }\n\n /**\n * Remove all auth credentials from config (logout)\n */\n clearAuth(): void {\n this.delete('apiKey');\n this.delete('jwtToken');\n this.delete('refreshToken');\n }\n\n /**\n * Remove API key from config (logout)\n */\n removeApiKey(): void {\n this.delete('apiKey');\n }\n\n /**\n * Set workspace ID in config\n */\n setWorkspaceId(workspaceId: string): void {\n this.set('workspaceId', workspaceId);\n }\n\n /**\n * Set base URL in config\n */\n setBaseUrl(baseUrl: string): void {\n this.set('baseUrl', baseUrl);\n }\n}\n\n// Export singleton instance\nexport const configStore = new ConfigStore();\n\n// Export class for testing purposes\nexport { ConfigStore };\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { CallScorecardResult } from '@chanl-ai/sdk';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared interactive utilities for live call/scenario monitoring
|
|
5
|
+
*
|
|
6
|
+
* Display functions for transcript segments, scorecards, and status.
|
|
7
|
+
* Polling logic has moved to the SDK's LiveCall/LiveExecution classes.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface TranscriptSegment {
|
|
11
|
+
speaker: string;
|
|
12
|
+
text: string;
|
|
13
|
+
start: number;
|
|
14
|
+
end: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Print a transcript segment with speaker label and timestamp
|
|
18
|
+
*/
|
|
19
|
+
declare function printSegment(segment: TranscriptSegment): void;
|
|
20
|
+
/**
|
|
21
|
+
* Format a speaker name for display
|
|
22
|
+
*/
|
|
23
|
+
declare function formatSpeaker(speaker: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Display a scorecard result in a formatted way
|
|
26
|
+
*/
|
|
27
|
+
declare function displayScorecard(results: CallScorecardResult[]): void;
|
|
28
|
+
/**
|
|
29
|
+
* Format elapsed time as MM:SS
|
|
30
|
+
*/
|
|
31
|
+
declare function formatElapsed(startTime: Date): string;
|
|
32
|
+
/**
|
|
33
|
+
* Terminal call statuses that mean the call is done
|
|
34
|
+
*/
|
|
35
|
+
declare const TERMINAL_CALL_STATUSES: Set<string>;
|
|
36
|
+
/**
|
|
37
|
+
* Check if a call status is terminal
|
|
38
|
+
*/
|
|
39
|
+
declare function isTerminalStatus(status: string): boolean;
|
|
40
|
+
|
|
41
|
+
export { TERMINAL_CALL_STATUSES, type TranscriptSegment, displayScorecard, formatElapsed, formatSpeaker, isTerminalStatus, printSegment };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { printInfo } from "./output.js";
|
|
3
|
+
function printSegment(segment) {
|
|
4
|
+
const speaker = formatSpeaker(segment.speaker);
|
|
5
|
+
const time = chalk.dim(`[${formatSeconds(segment.start)}]`);
|
|
6
|
+
console.log(` ${speaker} ${time}: ${segment.text}`);
|
|
7
|
+
}
|
|
8
|
+
function formatSpeaker(speaker) {
|
|
9
|
+
switch (speaker) {
|
|
10
|
+
case "speaker_0":
|
|
11
|
+
case "agent":
|
|
12
|
+
return chalk.cyan("Agent");
|
|
13
|
+
case "speaker_1":
|
|
14
|
+
case "customer":
|
|
15
|
+
return chalk.yellow("Customer");
|
|
16
|
+
case "persona":
|
|
17
|
+
return chalk.magenta("Persona");
|
|
18
|
+
default:
|
|
19
|
+
return chalk.dim(speaker);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function formatSeconds(seconds) {
|
|
23
|
+
const mins = Math.floor(seconds / 60);
|
|
24
|
+
const secs = Math.floor(seconds % 60).toString().padStart(2, "0");
|
|
25
|
+
return `${mins}:${secs}`;
|
|
26
|
+
}
|
|
27
|
+
function displayScorecard(results) {
|
|
28
|
+
if (!results || results.length === 0) {
|
|
29
|
+
printInfo("No scorecard results available");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const result of results) {
|
|
33
|
+
const overallScore = result.overallScore ?? 0;
|
|
34
|
+
const scoreColor = overallScore >= 80 ? chalk.green : overallScore >= 60 ? chalk.yellow : chalk.red;
|
|
35
|
+
console.log(chalk.bold(`
|
|
36
|
+
Scorecard: ${scoreColor(`${overallScore}/100`)}`));
|
|
37
|
+
if (result.criteriaResults && result.criteriaResults.length > 0) {
|
|
38
|
+
for (const criterion of result.criteriaResults) {
|
|
39
|
+
const passed = criterion.score >= 70;
|
|
40
|
+
const icon = passed ? chalk.green("\u2713") : chalk.red("\u2717");
|
|
41
|
+
const scoreStr = `(${criterion.score}/100)`;
|
|
42
|
+
const feedback = criterion.feedback ? chalk.dim(` \u2014 ${criterion.feedback}`) : "";
|
|
43
|
+
console.log(` ${icon} ${criterion.criterionName} ${scoreStr}${feedback}`);
|
|
44
|
+
}
|
|
45
|
+
} else if (result.categoryScores && result.categoryScores.length > 0) {
|
|
46
|
+
for (const cat of result.categoryScores) {
|
|
47
|
+
const passed = cat.score >= 70;
|
|
48
|
+
const icon = passed ? chalk.green("\u2713") : chalk.red("\u2717");
|
|
49
|
+
console.log(` ${icon} ${cat.categoryName} (${cat.score}/100)`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (result.feedback) {
|
|
53
|
+
console.log(chalk.dim(`
|
|
54
|
+
${result.feedback}`));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function formatElapsed(startTime) {
|
|
59
|
+
const elapsed = Math.floor((Date.now() - startTime.getTime()) / 1e3);
|
|
60
|
+
const mins = Math.floor(elapsed / 60).toString().padStart(2, "0");
|
|
61
|
+
const secs = (elapsed % 60).toString().padStart(2, "0");
|
|
62
|
+
return `${mins}:${secs}`;
|
|
63
|
+
}
|
|
64
|
+
const TERMINAL_CALL_STATUSES = /* @__PURE__ */ new Set([
|
|
65
|
+
"ended",
|
|
66
|
+
"completed",
|
|
67
|
+
"failed",
|
|
68
|
+
"no-answer",
|
|
69
|
+
"busy",
|
|
70
|
+
"cancelled"
|
|
71
|
+
]);
|
|
72
|
+
function isTerminalStatus(status) {
|
|
73
|
+
return TERMINAL_CALL_STATUSES.has(status);
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
TERMINAL_CALL_STATUSES,
|
|
77
|
+
displayScorecard,
|
|
78
|
+
formatElapsed,
|
|
79
|
+
formatSpeaker,
|
|
80
|
+
isTerminalStatus,
|
|
81
|
+
printSegment
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=interactive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/interactive.ts"],"sourcesContent":["/**\n * Shared interactive utilities for live call/scenario monitoring\n *\n * Display functions for transcript segments, scorecards, and status.\n * Polling logic has moved to the SDK's LiveCall/LiveExecution classes.\n */\n\nimport chalk from 'chalk';\nimport type { CallScorecardResult } from '@chanl-ai/sdk';\nimport { printInfo } from './output.js';\n\n// ==================== Transcript Display ====================\n\nexport interface TranscriptSegment {\n speaker: string;\n text: string;\n start: number;\n end: number;\n}\n\n/**\n * Print a transcript segment with speaker label and timestamp\n */\nexport function printSegment(segment: TranscriptSegment): void {\n const speaker = formatSpeaker(segment.speaker);\n const time = chalk.dim(`[${formatSeconds(segment.start)}]`);\n console.log(` ${speaker} ${time}: ${segment.text}`);\n}\n\n/**\n * Format a speaker name for display\n */\nexport function formatSpeaker(speaker: string): string {\n switch (speaker) {\n case 'speaker_0':\n case 'agent':\n return chalk.cyan('Agent');\n case 'speaker_1':\n case 'customer':\n return chalk.yellow('Customer');\n case 'persona':\n return chalk.magenta('Persona');\n default:\n return chalk.dim(speaker);\n }\n}\n\n/**\n * Format seconds as M:SS\n */\nfunction formatSeconds(seconds: number): string {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60).toString().padStart(2, '0');\n return `${mins}:${secs}`;\n}\n\n// ==================== Scorecard Display ====================\n\n/**\n * Display a scorecard result in a formatted way\n */\nexport function displayScorecard(results: CallScorecardResult[]): void {\n if (!results || results.length === 0) {\n printInfo('No scorecard results available');\n return;\n }\n\n for (const result of results) {\n const overallScore = result.overallScore ?? 0;\n const scoreColor = overallScore >= 80 ? chalk.green : overallScore >= 60 ? chalk.yellow : chalk.red;\n\n console.log(chalk.bold(`\\n Scorecard: ${scoreColor(`${overallScore}/100`)}`));\n\n if (result.criteriaResults && result.criteriaResults.length > 0) {\n for (const criterion of result.criteriaResults) {\n const passed = criterion.score >= 70;\n const icon = passed ? chalk.green('✓') : chalk.red('✗');\n const scoreStr = `(${criterion.score}/100)`;\n const feedback = criterion.feedback ? chalk.dim(` — ${criterion.feedback}`) : '';\n console.log(` ${icon} ${criterion.criterionName} ${scoreStr}${feedback}`);\n }\n } else if (result.categoryScores && result.categoryScores.length > 0) {\n for (const cat of result.categoryScores) {\n const passed = cat.score >= 70;\n const icon = passed ? chalk.green('✓') : chalk.red('✗');\n console.log(` ${icon} ${cat.categoryName} (${cat.score}/100)`);\n }\n }\n\n if (result.feedback) {\n console.log(chalk.dim(`\\n ${result.feedback}`));\n }\n }\n}\n\n// ==================== Status Line ====================\n\n/**\n * Format elapsed time as MM:SS\n */\nexport function formatElapsed(startTime: Date): string {\n const elapsed = Math.floor((Date.now() - startTime.getTime()) / 1000);\n const mins = Math.floor(elapsed / 60).toString().padStart(2, '0');\n const secs = (elapsed % 60).toString().padStart(2, '0');\n return `${mins}:${secs}`;\n}\n\n// ==================== Call Status ====================\n\n/**\n * Terminal call statuses that mean the call is done\n */\nexport const TERMINAL_CALL_STATUSES = new Set([\n 'ended', 'completed', 'failed', 'no-answer', 'busy', 'cancelled',\n]);\n\n/**\n * Check if a call status is terminal\n */\nexport function isTerminalStatus(status: string): boolean {\n return TERMINAL_CALL_STATUSES.has(status);\n}\n"],"mappings":"AAOA,OAAO,WAAW;AAElB,SAAS,iBAAiB;AAcnB,SAAS,aAAa,SAAkC;AAC7D,QAAM,UAAU,cAAc,QAAQ,OAAO;AAC7C,QAAM,OAAO,MAAM,IAAI,IAAI,cAAc,QAAQ,KAAK,CAAC,GAAG;AAC1D,UAAQ,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,QAAQ,IAAI,EAAE;AACrD;AAKO,SAAS,cAAc,SAAyB;AACrD,UAAQ,SAAS;AAAA,IACf,KAAK;AAAA,IACL,KAAK;AACH,aAAO,MAAM,KAAK,OAAO;AAAA,IAC3B,KAAK;AAAA,IACL,KAAK;AACH,aAAO,MAAM,OAAO,UAAU;AAAA,IAChC,KAAK;AACH,aAAO,MAAM,QAAQ,SAAS;AAAA,IAChC;AACE,aAAO,MAAM,IAAI,OAAO;AAAA,EAC5B;AACF;AAKA,SAAS,cAAc,SAAyB;AAC9C,QAAM,OAAO,KAAK,MAAM,UAAU,EAAE;AACpC,QAAM,OAAO,KAAK,MAAM,UAAU,EAAE,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AAChE,SAAO,GAAG,IAAI,IAAI,IAAI;AACxB;AAOO,SAAS,iBAAiB,SAAsC;AACrE,MAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AACpC,cAAU,gCAAgC;AAC1C;AAAA,EACF;AAEA,aAAW,UAAU,SAAS;AAC5B,UAAM,eAAe,OAAO,gBAAgB;AAC5C,UAAM,aAAa,gBAAgB,KAAK,MAAM,QAAQ,gBAAgB,KAAK,MAAM,SAAS,MAAM;AAEhG,YAAQ,IAAI,MAAM,KAAK;AAAA,eAAkB,WAAW,GAAG,YAAY,MAAM,CAAC,EAAE,CAAC;AAE7E,QAAI,OAAO,mBAAmB,OAAO,gBAAgB,SAAS,GAAG;AAC/D,iBAAW,aAAa,OAAO,iBAAiB;AAC9C,cAAM,SAAS,UAAU,SAAS;AAClC,cAAM,OAAO,SAAS,MAAM,MAAM,QAAG,IAAI,MAAM,IAAI,QAAG;AACtD,cAAM,WAAW,IAAI,UAAU,KAAK;AACpC,cAAM,WAAW,UAAU,WAAW,MAAM,IAAI,WAAM,UAAU,QAAQ,EAAE,IAAI;AAC9E,gBAAQ,IAAI,OAAO,IAAI,IAAI,UAAU,aAAa,IAAI,QAAQ,GAAG,QAAQ,EAAE;AAAA,MAC7E;AAAA,IACF,WAAW,OAAO,kBAAkB,OAAO,eAAe,SAAS,GAAG;AACpE,iBAAW,OAAO,OAAO,gBAAgB;AACvC,cAAM,SAAS,IAAI,SAAS;AAC5B,cAAM,OAAO,SAAS,MAAM,MAAM,QAAG,IAAI,MAAM,IAAI,QAAG;AACtD,gBAAQ,IAAI,OAAO,IAAI,IAAI,IAAI,YAAY,KAAK,IAAI,KAAK,OAAO;AAAA,MAClE;AAAA,IACF;AAEA,QAAI,OAAO,UAAU;AACnB,cAAQ,IAAI,MAAM,IAAI;AAAA,MAAS,OAAO,QAAQ,EAAE,CAAC;AAAA,IACnD;AAAA,EACF;AACF;AAOO,SAAS,cAAc,WAAyB;AACrD,QAAM,UAAU,KAAK,OAAO,KAAK,IAAI,IAAI,UAAU,QAAQ,KAAK,GAAI;AACpE,QAAM,OAAO,KAAK,MAAM,UAAU,EAAE,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AAChE,QAAM,QAAQ,UAAU,IAAI,SAAS,EAAE,SAAS,GAAG,GAAG;AACtD,SAAO,GAAG,IAAI,IAAI,IAAI;AACxB;AAOO,MAAM,yBAAyB,oBAAI,IAAI;AAAA,EAC5C;AAAA,EAAS;AAAA,EAAa;AAAA,EAAU;AAAA,EAAa;AAAA,EAAQ;AACvD,CAAC;AAKM,SAAS,iBAAiB,QAAyB;AACxD,SAAO,uBAAuB,IAAI,MAAM;AAC1C;","names":[]}
|