@chanl/cli 2.0.4 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/agents.test.js +574 -0
- package/dist/__tests__/agents.test.js.map +1 -0
- package/dist/__tests__/auth.test.d.ts +2 -0
- package/dist/__tests__/auth.test.js +87 -0
- package/dist/__tests__/auth.test.js.map +1 -0
- package/dist/__tests__/calls.test.d.ts +2 -0
- package/dist/__tests__/calls.test.js +115 -0
- package/dist/__tests__/calls.test.js.map +1 -0
- package/dist/__tests__/chat.test.d.ts +2 -0
- package/dist/__tests__/chat.test.js +357 -0
- package/dist/__tests__/chat.test.js.map +1 -0
- package/dist/__tests__/cli-base.test.d.ts +2 -0
- package/dist/__tests__/cli-base.test.js +87 -0
- package/dist/__tests__/cli-base.test.js.map +1 -0
- package/dist/__tests__/cli-missing.test.d.ts +2 -0
- package/dist/__tests__/cli-missing.test.js +546 -0
- package/dist/__tests__/cli-missing.test.js.map +1 -0
- package/dist/__tests__/helpers.d.ts +234 -0
- package/dist/__tests__/helpers.js +314 -0
- package/dist/__tests__/helpers.js.map +1 -0
- package/dist/__tests__/mcp.test.d.ts +2 -0
- package/dist/__tests__/mcp.test.js +470 -0
- package/dist/__tests__/mcp.test.js.map +1 -0
- package/dist/__tests__/prompts.test.d.ts +2 -0
- package/dist/__tests__/prompts.test.js +227 -0
- package/dist/__tests__/prompts.test.js.map +1 -0
- package/dist/__tests__/scenarios.test.d.ts +2 -0
- package/dist/__tests__/scenarios.test.js +270 -0
- package/dist/__tests__/scenarios.test.js.map +1 -0
- package/dist/__tests__/tools.test.d.ts +2 -0
- package/dist/__tests__/tools.test.js +331 -0
- package/dist/__tests__/tools.test.js.map +1 -0
- package/dist/__tests__/toolsets.test.d.ts +2 -0
- package/dist/__tests__/toolsets.test.js +196 -0
- package/dist/__tests__/toolsets.test.js.map +1 -0
- package/dist/__tests__/workspaces.test.d.ts +2 -0
- package/dist/__tests__/workspaces.test.js +155 -0
- package/dist/__tests__/workspaces.test.js.map +1 -0
- package/dist/commands/agents.js +96 -6
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/chat.js +2 -2
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/config.js +24 -2
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/memory.js +134 -1
- package/dist/commands/memory.js.map +1 -1
- package/dist/commands/prompts.js +148 -1
- package/dist/commands/prompts.js.map +1 -1
- package/dist/commands/scorecards.js +3 -3
- package/dist/commands/scorecards.js.map +1 -1
- package/dist/utils/config-store.d.ts +8 -0
- package/dist/utils/config-store.js +18 -1
- package/dist/utils/config-store.js.map +1 -1
- package/dist/utils/sdk-factory.js +15 -3
- package/dist/utils/sdk-factory.js.map +1 -1
- package/package.json +4 -4
- package/dist/__tests__/cli.test.js +0 -2308
- package/dist/__tests__/cli.test.js.map +0 -1
- /package/dist/__tests__/{cli.test.d.ts → agents.test.d.ts} +0 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import { configStore } from "../utils/config-store";
|
|
3
|
+
import { ChanlSDK } from "@chanl/sdk";
|
|
4
|
+
import {
|
|
5
|
+
runCli,
|
|
6
|
+
makeMockSdk,
|
|
7
|
+
setupAuthenticatedConfigStore
|
|
8
|
+
} from "./helpers";
|
|
9
|
+
vi.mock("@chanl/sdk", () => ({
|
|
10
|
+
ChanlSDK: vi.fn()
|
|
11
|
+
}));
|
|
12
|
+
vi.mock("../utils/config-store", () => ({
|
|
13
|
+
configStore: {
|
|
14
|
+
getApiKey: vi.fn(),
|
|
15
|
+
getBaseUrl: vi.fn(() => "https://api.chanl.ai"),
|
|
16
|
+
getWorkspaceId: vi.fn(() => "ws_123"),
|
|
17
|
+
getJwtToken: vi.fn(() => null),
|
|
18
|
+
getAuthMethod: vi.fn(() => null),
|
|
19
|
+
getAppUrl: vi.fn(() => "https://app.chanl.ai"),
|
|
20
|
+
getDeployment: vi.fn(() => "cloud"),
|
|
21
|
+
getApiPrefix: vi.fn(() => "/api/v1"),
|
|
22
|
+
setApiKey: vi.fn(),
|
|
23
|
+
setBaseUrl: vi.fn(),
|
|
24
|
+
setWorkspaceId: vi.fn(),
|
|
25
|
+
removeApiKey: vi.fn(),
|
|
26
|
+
clearAuth: vi.fn(),
|
|
27
|
+
delete: vi.fn(),
|
|
28
|
+
isAuthenticated: vi.fn(),
|
|
29
|
+
getPath: vi.fn(() => "/home/user/.chanl/config.json")
|
|
30
|
+
}
|
|
31
|
+
}));
|
|
32
|
+
describe("CLI", () => {
|
|
33
|
+
let mockSdk;
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
vi.clearAllMocks();
|
|
36
|
+
mockSdk = makeMockSdk();
|
|
37
|
+
ChanlSDK.mockImplementation(() => mockSdk);
|
|
38
|
+
setupAuthenticatedConfigStore(configStore);
|
|
39
|
+
});
|
|
40
|
+
afterEach(() => {
|
|
41
|
+
process.exitCode = void 0;
|
|
42
|
+
});
|
|
43
|
+
describe("workspaces list", () => {
|
|
44
|
+
it("should list workspaces with table output", async () => {
|
|
45
|
+
mockSdk.workspace.getAll.mockResolvedValue({
|
|
46
|
+
success: true,
|
|
47
|
+
data: [
|
|
48
|
+
{
|
|
49
|
+
id: "ws_abc123",
|
|
50
|
+
name: "My Workspace",
|
|
51
|
+
description: "Main workspace",
|
|
52
|
+
createdAt: "2025-01-01T00:00:00Z",
|
|
53
|
+
updatedAt: "2025-01-15T10:30:00Z"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "ws_def456",
|
|
57
|
+
name: "Test Workspace",
|
|
58
|
+
description: "Testing environment",
|
|
59
|
+
createdAt: "2025-02-01T00:00:00Z",
|
|
60
|
+
updatedAt: "2025-02-05T10:30:00Z"
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
message: "Success",
|
|
64
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
65
|
+
});
|
|
66
|
+
const { logs, exitCode } = await runCli(["workspaces", "list"]);
|
|
67
|
+
expect(exitCode).toBe(0);
|
|
68
|
+
expect(mockSdk.workspace.getAll).toHaveBeenCalled();
|
|
69
|
+
const output = logs.join("\n");
|
|
70
|
+
expect(output).toContain("My Workspace");
|
|
71
|
+
expect(output).toContain("Test Workspace");
|
|
72
|
+
});
|
|
73
|
+
it("should list workspaces with JSON output", async () => {
|
|
74
|
+
const mockWorkspaces = [
|
|
75
|
+
{
|
|
76
|
+
id: "ws_abc123",
|
|
77
|
+
name: "My Workspace",
|
|
78
|
+
description: "Main workspace",
|
|
79
|
+
createdAt: "2025-01-01T00:00:00Z",
|
|
80
|
+
updatedAt: "2025-01-15T10:30:00Z"
|
|
81
|
+
}
|
|
82
|
+
];
|
|
83
|
+
mockSdk.workspace.getAll.mockResolvedValue({
|
|
84
|
+
success: true,
|
|
85
|
+
data: mockWorkspaces,
|
|
86
|
+
message: "Success",
|
|
87
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
88
|
+
});
|
|
89
|
+
const { logs, exitCode } = await runCli(["--json", "workspaces", "list"]);
|
|
90
|
+
expect(exitCode).toBe(0);
|
|
91
|
+
const output = logs.join("\n");
|
|
92
|
+
const parsed = JSON.parse(output);
|
|
93
|
+
expect(parsed).toHaveLength(1);
|
|
94
|
+
expect(parsed[0].name).toBe("My Workspace");
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe("workspaces get", () => {
|
|
98
|
+
it("should get workspace details by ID", async () => {
|
|
99
|
+
mockSdk.workspace.getById.mockResolvedValue({
|
|
100
|
+
success: true,
|
|
101
|
+
data: {
|
|
102
|
+
id: "ws_abc123",
|
|
103
|
+
name: "My Workspace",
|
|
104
|
+
description: "Main workspace",
|
|
105
|
+
settings: { timezone: "UTC" },
|
|
106
|
+
createdAt: "2025-01-01T00:00:00Z",
|
|
107
|
+
updatedAt: "2025-01-15T10:30:00Z"
|
|
108
|
+
},
|
|
109
|
+
message: "Success",
|
|
110
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
111
|
+
});
|
|
112
|
+
const { logs, exitCode } = await runCli(["workspaces", "get", "ws_abc123"]);
|
|
113
|
+
expect(exitCode).toBe(0);
|
|
114
|
+
expect(mockSdk.workspace.getById).toHaveBeenCalledWith("ws_abc123");
|
|
115
|
+
const output = logs.join("\n");
|
|
116
|
+
expect(output).toContain("My Workspace");
|
|
117
|
+
expect(output).toContain("ws_abc123");
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe("workspaces use", () => {
|
|
121
|
+
it("should set active workspace", async () => {
|
|
122
|
+
mockSdk.workspace.getById.mockResolvedValue({
|
|
123
|
+
success: true,
|
|
124
|
+
data: {
|
|
125
|
+
id: "ws_abc123",
|
|
126
|
+
name: "My Workspace",
|
|
127
|
+
description: "Main workspace",
|
|
128
|
+
settings: {},
|
|
129
|
+
createdAt: "2025-01-01T00:00:00Z",
|
|
130
|
+
updatedAt: "2025-01-15T10:30:00Z"
|
|
131
|
+
},
|
|
132
|
+
message: "Success",
|
|
133
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
134
|
+
});
|
|
135
|
+
const { logs, exitCode } = await runCli(["workspaces", "use", "ws_abc123"]);
|
|
136
|
+
expect(exitCode).toBe(0);
|
|
137
|
+
expect(configStore.setWorkspaceId).toHaveBeenCalledWith("ws_abc123");
|
|
138
|
+
const output = logs.join("\n");
|
|
139
|
+
expect(output).toContain("ws_abc123");
|
|
140
|
+
});
|
|
141
|
+
it("should handle invalid workspace ID", async () => {
|
|
142
|
+
mockSdk.workspace.getById.mockResolvedValue({
|
|
143
|
+
success: false,
|
|
144
|
+
data: null,
|
|
145
|
+
message: "Workspace not found",
|
|
146
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
147
|
+
});
|
|
148
|
+
const { exitCode, errors } = await runCli(["workspaces", "use", "ws_invalid"]);
|
|
149
|
+
expect(exitCode).toBe(1);
|
|
150
|
+
expect(errors.some((e) => e.includes("not found") || e.includes("Failed"))).toBe(true);
|
|
151
|
+
expect(configStore.setWorkspaceId).not.toHaveBeenCalled();
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
//# sourceMappingURL=workspaces.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/__tests__/workspaces.test.ts"],"sourcesContent":["/**\n * CLI workspaces tests — workspaces list, workspaces get, workspaces use\n */\n\nimport { describe, it, expect, beforeEach, afterEach, vi, Mock } from 'vitest';\nimport { configStore } from '../utils/config-store';\nimport { ChanlSDK } from '@chanl/sdk';\nimport {\n runCli,\n makeMockSdk,\n setupAuthenticatedConfigStore,\n type MockSdk,\n} from './helpers';\n\n// Mock the SDK\nvi.mock('@chanl/sdk', () => ({\n ChanlSDK: vi.fn(),\n}));\n\n// Mock config store\nvi.mock('../utils/config-store', () => ({\n configStore: {\n getApiKey: vi.fn(),\n getBaseUrl: vi.fn(() => 'https://api.chanl.ai'),\n getWorkspaceId: vi.fn(() => 'ws_123'),\n getJwtToken: vi.fn(() => null),\n getAuthMethod: vi.fn(() => null),\n getAppUrl: vi.fn(() => 'https://app.chanl.ai'),\n getDeployment: vi.fn(() => 'cloud'),\n getApiPrefix: vi.fn(() => '/api/v1'),\n setApiKey: vi.fn(),\n setBaseUrl: vi.fn(),\n setWorkspaceId: vi.fn(),\n removeApiKey: vi.fn(),\n clearAuth: vi.fn(),\n delete: vi.fn(),\n isAuthenticated: vi.fn(),\n getPath: vi.fn(() => '/home/user/.chanl/config.json'),\n },\n}));\n\ndescribe('CLI', () => {\n let mockSdk: MockSdk;\n\n beforeEach(() => {\n vi.clearAllMocks();\n mockSdk = makeMockSdk();\n (ChanlSDK as Mock).mockImplementation(() => mockSdk);\n setupAuthenticatedConfigStore(configStore as unknown as {\n getApiKey: Mock;\n getWorkspaceId: Mock;\n isAuthenticated: Mock;\n });\n });\n\n afterEach(() => {\n process.exitCode = undefined;\n });\n\n // ==========================================================================\n // WORKSPACES CLI TESTS (Story 9)\n // ==========================================================================\n\n describe('workspaces list', () => {\n it('should list workspaces with table output', async () => {\n mockSdk.workspace.getAll.mockResolvedValue({\n success: true,\n data: [\n {\n id: 'ws_abc123',\n name: 'My Workspace',\n description: 'Main workspace',\n createdAt: '2025-01-01T00:00:00Z',\n updatedAt: '2025-01-15T10:30:00Z',\n },\n {\n id: 'ws_def456',\n name: 'Test Workspace',\n description: 'Testing environment',\n createdAt: '2025-02-01T00:00:00Z',\n updatedAt: '2025-02-05T10:30:00Z',\n },\n ],\n message: 'Success',\n timestamp: new Date().toISOString(),\n });\n\n const { logs, exitCode } = await runCli(['workspaces', 'list']);\n\n expect(exitCode).toBe(0);\n expect(mockSdk.workspace.getAll).toHaveBeenCalled();\n\n const output = logs.join('\\n');\n expect(output).toContain('My Workspace');\n expect(output).toContain('Test Workspace');\n });\n\n it('should list workspaces with JSON output', async () => {\n const mockWorkspaces = [\n {\n id: 'ws_abc123',\n name: 'My Workspace',\n description: 'Main workspace',\n createdAt: '2025-01-01T00:00:00Z',\n updatedAt: '2025-01-15T10:30:00Z',\n },\n ];\n\n mockSdk.workspace.getAll.mockResolvedValue({\n success: true,\n data: mockWorkspaces,\n message: 'Success',\n timestamp: new Date().toISOString(),\n });\n\n const { logs, exitCode } = await runCli(['--json', 'workspaces', 'list']);\n\n expect(exitCode).toBe(0);\n\n const output = logs.join('\\n');\n const parsed = JSON.parse(output);\n expect(parsed).toHaveLength(1);\n expect(parsed[0].name).toBe('My Workspace');\n });\n });\n\n describe('workspaces get', () => {\n it('should get workspace details by ID', async () => {\n mockSdk.workspace.getById.mockResolvedValue({\n success: true,\n data: {\n id: 'ws_abc123',\n name: 'My Workspace',\n description: 'Main workspace',\n settings: { timezone: 'UTC' },\n createdAt: '2025-01-01T00:00:00Z',\n updatedAt: '2025-01-15T10:30:00Z',\n },\n message: 'Success',\n timestamp: new Date().toISOString(),\n });\n\n const { logs, exitCode } = await runCli(['workspaces', 'get', 'ws_abc123']);\n\n expect(exitCode).toBe(0);\n expect(mockSdk.workspace.getById).toHaveBeenCalledWith('ws_abc123');\n\n const output = logs.join('\\n');\n expect(output).toContain('My Workspace');\n expect(output).toContain('ws_abc123');\n });\n });\n\n describe('workspaces use', () => {\n it('should set active workspace', async () => {\n mockSdk.workspace.getById.mockResolvedValue({\n success: true,\n data: {\n id: 'ws_abc123',\n name: 'My Workspace',\n description: 'Main workspace',\n settings: {},\n createdAt: '2025-01-01T00:00:00Z',\n updatedAt: '2025-01-15T10:30:00Z',\n },\n message: 'Success',\n timestamp: new Date().toISOString(),\n });\n\n const { logs, exitCode } = await runCli(['workspaces', 'use', 'ws_abc123']);\n\n expect(exitCode).toBe(0);\n expect(configStore.setWorkspaceId).toHaveBeenCalledWith('ws_abc123');\n\n const output = logs.join('\\n');\n expect(output).toContain('ws_abc123');\n });\n\n it('should handle invalid workspace ID', async () => {\n mockSdk.workspace.getById.mockResolvedValue({\n success: false,\n data: null,\n message: 'Workspace not found',\n timestamp: new Date().toISOString(),\n });\n\n const { exitCode, errors } = await runCli(['workspaces', 'use', 'ws_invalid']);\n\n expect(exitCode).toBe(1);\n expect(errors.some((e) => e.includes('not found') || e.includes('Failed'))).toBe(true);\n expect(configStore.setWorkspaceId).not.toHaveBeenCalled();\n });\n });\n});\n"],"mappings":"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","names":[]}
|
package/dist/commands/agents.js
CHANGED
|
@@ -27,7 +27,9 @@ Quick Start:
|
|
|
27
27
|
$ chanl agents list # List all agents
|
|
28
28
|
$ chanl agents get <id> # View agent details
|
|
29
29
|
$ chanl agents sync vapi # Sync from VAPI
|
|
30
|
-
$ chanl agents
|
|
30
|
+
$ chanl agents templates # List provisionable templates
|
|
31
|
+
$ chanl agents create --from-template lead-qualifier --name "Lead Gen Bot"
|
|
32
|
+
$ chanl agents create --template vapi # Generate local VAPI scaffold
|
|
31
33
|
$ chanl agents stats # View statistics
|
|
32
34
|
|
|
33
35
|
Workflow:
|
|
@@ -52,15 +54,29 @@ Examples:
|
|
|
52
54
|
$ chanl agents get abc123 # Get agent details
|
|
53
55
|
$ chanl agents get abc123 --json # Output as JSON`
|
|
54
56
|
).action(handleAgentsGet);
|
|
55
|
-
agents.command("
|
|
57
|
+
agents.command("templates").description("List registry templates you can provision an agent from").addHelpText(
|
|
56
58
|
"after",
|
|
57
59
|
`
|
|
58
60
|
Examples:
|
|
59
|
-
$ chanl agents
|
|
60
|
-
$ chanl agents
|
|
61
|
+
$ chanl agents templates # List registry templates
|
|
62
|
+
$ chanl agents templates --json # Output as JSON
|
|
63
|
+
|
|
64
|
+
Provision one with:
|
|
65
|
+
$ chanl agents create --from-template lead-qualifier --name "My Agent"`
|
|
66
|
+
).action(handleAgentsTemplates);
|
|
67
|
+
agents.command("create").description("Create a new agent").option("-f, --file <path>", "Path to JSON file with agent data").option("--template [platform]", "Output a local scaffold JSON (vapi, elevenlabs, custom) \u2014 no server call").option("--from-template <templateId>", "Provision from a registry template (see 'chanl agents templates')").option("-n, --name <name>", "Agent name (used with --from-template)").addHelpText(
|
|
68
|
+
"after",
|
|
69
|
+
`
|
|
70
|
+
Examples:
|
|
71
|
+
$ chanl agents create --from-template lead-qualifier --name "Lead Gen Bot"
|
|
72
|
+
# Provision from registry template
|
|
73
|
+
$ chanl agents create --template vapi > agent.json # VAPI scaffold JSON (local, no server call)
|
|
74
|
+
$ chanl agents create --template custom > agent.json # Custom scaffold JSON
|
|
61
75
|
$ chanl agents create -f agent.json # Create from file
|
|
62
76
|
|
|
63
|
-
|
|
77
|
+
'--from-template' creates a real, configured agent via the platform's template
|
|
78
|
+
registry (run 'chanl agents templates' to see what's available). '--template'
|
|
79
|
+
just prints a local JSON scaffold to fill in yourself.`
|
|
64
80
|
).action(handleAgentsCreate);
|
|
65
81
|
agents.command("update <id>").description("Update an existing agent").option("-f, --file <path>", "Path to JSON file with update data").option("--sync-to-vapi", "Sync changes back to VAPI platform").addHelpText(
|
|
66
82
|
"after",
|
|
@@ -293,6 +309,73 @@ async function handleAgentsGet(id) {
|
|
|
293
309
|
process.exitCode = 1;
|
|
294
310
|
}
|
|
295
311
|
}
|
|
312
|
+
async function handleAgentsTemplates() {
|
|
313
|
+
const sdk = createSdk();
|
|
314
|
+
if (!sdk) return;
|
|
315
|
+
const spinner = ora("Fetching templates...").start();
|
|
316
|
+
try {
|
|
317
|
+
const response = await sdk.agents.listTemplates();
|
|
318
|
+
spinner.stop();
|
|
319
|
+
if (!response.success || !response.data) {
|
|
320
|
+
printError("Failed to fetch templates", response.message);
|
|
321
|
+
process.exitCode = 1;
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
const { templates } = response.data;
|
|
325
|
+
if (isJsonOutput()) {
|
|
326
|
+
printJson(response.data);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (templates.length === 0) {
|
|
330
|
+
printInfo("No templates available");
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
printBlank();
|
|
334
|
+
printSimpleTable(
|
|
335
|
+
["ID", "Name", "Version", "Description"],
|
|
336
|
+
templates.map((t) => [t.id, t.name, t.version.toString(), t.description])
|
|
337
|
+
);
|
|
338
|
+
printBlank();
|
|
339
|
+
printInfo('Provision one with: chanl agents create --from-template <id> --name "My Agent"');
|
|
340
|
+
} catch (error) {
|
|
341
|
+
spinner.fail("Failed to fetch templates");
|
|
342
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
343
|
+
printError("Error", message);
|
|
344
|
+
process.exitCode = 1;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
async function handleAgentsCreateFromTemplate(templateId, name) {
|
|
348
|
+
if (!name) {
|
|
349
|
+
printError("Missing required option", "Use '-n, --name <name>' together with --from-template");
|
|
350
|
+
process.exitCode = 1;
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const sdk = createSdk();
|
|
354
|
+
if (!sdk) return;
|
|
355
|
+
const spinner = ora(`Provisioning agent from template '${templateId}'...`).start();
|
|
356
|
+
try {
|
|
357
|
+
const response = await sdk.agents.createFromTemplate(templateId, { name });
|
|
358
|
+
spinner.stop();
|
|
359
|
+
if (!response.success || !response.data) {
|
|
360
|
+
printError("Failed to create agent from template", response.message);
|
|
361
|
+
process.exitCode = 1;
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
if (isJsonOutput()) {
|
|
365
|
+
printJson(response.data);
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const agent = response.data;
|
|
369
|
+
printSuccess(`Agent created from template: ${agent.name}`);
|
|
370
|
+
printLabel("ID", agent.id);
|
|
371
|
+
printLabel("Template", templateId);
|
|
372
|
+
} catch (error) {
|
|
373
|
+
spinner.fail("Failed to create agent from template");
|
|
374
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
375
|
+
printError("Error", message);
|
|
376
|
+
process.exitCode = 1;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
296
379
|
async function handleAgentsCreate(options) {
|
|
297
380
|
if (options.template !== void 0) {
|
|
298
381
|
const platform = typeof options.template === "string" ? options.template : "custom";
|
|
@@ -300,8 +383,15 @@ async function handleAgentsCreate(options) {
|
|
|
300
383
|
console.log(JSON.stringify(template, null, 2));
|
|
301
384
|
return;
|
|
302
385
|
}
|
|
386
|
+
if (options.fromTemplate) {
|
|
387
|
+
await handleAgentsCreateFromTemplate(options.fromTemplate, options.name);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
303
390
|
if (!options.file) {
|
|
304
|
-
printError(
|
|
391
|
+
printError(
|
|
392
|
+
"Missing required option",
|
|
393
|
+
"Use '-f <file>' for agent data, '--from-template <id>' to provision from a registry template, or '--template [platform]' for a local scaffold"
|
|
394
|
+
);
|
|
305
395
|
process.exitCode = 1;
|
|
306
396
|
return;
|
|
307
397
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/agents.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { readFileSync } from 'fs';\nimport type { Agent, CreateAgentData, SyncAgentsResult } from '@chanl/sdk';\nimport { createSdk } from '../utils/sdk-factory.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 agents command group\n */\nexport function createAgentsCommand(): Command {\n const agents = new Command('agents')\n .description('Manage AI agents (VAPI, ElevenLabs, custom)')\n .addHelpText(\n 'after',\n `\nWhat are Agents?\n Agents are AI-powered voice assistants from various platforms (VAPI, ElevenLabs)\n or custom implementations. They can be tested with scenarios and analyzed with\n scorecards.\n\nQuick Start:\n $ chanl agents list # List all agents\n $ chanl agents get <id> # View agent details\n $ chanl agents sync vapi # Sync from VAPI\n $ chanl agents create --template vapi # Generate VAPI template\n $ chanl agents stats # View statistics\n\nWorkflow:\n 1. Sync agents from your platform (vapi, elevenlabs)\n 2. Or create custom agents with 'create -f agent.json'\n 3. Test agents with 'chanl scenarios run <id> --agent <agentId>'\n 4. Analyze results with 'chanl calls analysis <id>'`\n );\n\n // agents list\n agents\n .command('list')\n .description('List all agents')\n .option('-p, --platform <platform>', 'Filter by platform (vapi, elevenlabs, custom)')\n .option('-s, --status <status>', 'Filter by status (active, inactive)')\n .option('-l, --limit <number>', 'Number of items per page', '20')\n .option('--page <number>', 'Page number', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents list # List all agents\n $ chanl agents list --platform vapi # Filter by platform\n $ chanl agents list --status active # Only active agents\n $ chanl agents list --json # Output as JSON`\n )\n .action(handleAgentsList);\n\n // agents get <id>\n agents\n .command('get <id>')\n .description('Get agent details')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents get abc123 # Get agent details\n $ chanl agents get abc123 --json # Output as JSON`\n )\n .action(handleAgentsGet);\n\n // agents create\n agents\n .command('create')\n .description('Create a new agent')\n .option('-f, --file <path>', 'Path to JSON file with agent data')\n .option('--template [platform]', 'Output a template JSON (vapi, elevenlabs, custom)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents create --template vapi > agent.json # VAPI template\n $ chanl agents create --template custom > agent.json # Custom template\n $ chanl agents create -f agent.json # Create from file\n\nTemplates include platform-specific configurations and examples.`\n )\n .action(handleAgentsCreate);\n\n // agents update <id>\n agents\n .command('update <id>')\n .description('Update an existing agent')\n .option('-f, --file <path>', 'Path to JSON file with update data')\n .option('--sync-to-vapi', 'Sync changes back to VAPI platform')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents update abc123 -f updates.json\n $ chanl agents update abc123 -f updates.json --sync-to-vapi`\n )\n .action(handleAgentsUpdate);\n\n // agents delete <id>\n agents\n .command('delete <id>')\n .description('Delete an agent')\n .option('-y, --yes', 'Skip confirmation prompt')\n .option('--delete-from-integration', 'Also delete from platform (VAPI, etc.)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents delete abc123\n $ chanl agents delete abc123 --delete-from-integration`\n )\n .action(handleAgentsDelete);\n\n // agents sync <platform>\n agents\n .command('sync <platform>')\n .description('Sync agents from a platform (vapi, bland, twilio)')\n .option('-f, --force', 'Force update existing agents')\n .option('--clean', 'Delete all existing agents for this platform before sync')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents sync vapi # Sync from VAPI\n $ chanl agents sync vapi --force # Force update all\n $ chanl agents sync vapi --clean # Clean sync (delete first)`\n )\n .action(handleAgentsSync);\n\n // agents sync-all\n agents\n .command('sync-all')\n .description('Sync agents from all configured platforms')\n .option('-f, --force', 'Force update existing agents')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents sync-all # Sync from all platforms\n $ chanl agents sync-all --force # Force update all`\n )\n .action(handleAgentsSyncAll);\n\n // agents import\n agents\n .command('import')\n .description('Import a specific agent from a third-party platform')\n .requiredOption('--from <platform>', 'Source platform (vapi, retell, bland)')\n .requiredOption('--agent-id <id>', 'External agent ID on the source platform')\n .option('-n, --name <name>', 'Override the agent name')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents import --from vapi --agent-id asst_abc123\n $ chanl agents import --from retell --agent-id ret_xyz --name \"My Agent\"\n $ chanl agents import --from vapi --agent-id asst_abc --json`\n )\n .action(handleAgentsImport);\n\n // agents publish\n agents\n .command('publish <agent-id>')\n .description('Publish an agent to a third-party platform')\n .requiredOption('--to <platform>', 'Target platform (vapi, retell, bland)')\n .option('--target <ext-id>', 'External agent ID to update (omit to create new)')\n .option('--with-mcp', 'Include MCP URL for tool access')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents publish agent_123 --to vapi\n $ chanl agents publish agent_123 --to vapi --with-mcp\n $ chanl agents publish agent_123 --to vapi --target ext_456\n $ chanl agents publish agent_123 --to vapi --json`\n )\n .action(handleAgentsPublish);\n\n // agents push-mcp\n agents\n .command('push-mcp <agent-id>')\n .description('Push MCP URL to a third-party agent for tool access')\n .requiredOption('--to <platform>', 'Target platform (vapi, retell, bland)')\n .option('--target <ext-id>', 'External agent ID (omit to use default)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents push-mcp agent_123 --to vapi\n $ chanl agents push-mcp agent_123 --to vapi --target ext_456\n $ chanl agents push-mcp agent_123 --to vapi --json`\n )\n .action(handleAgentsPushMcp);\n\n // agents stats\n agents\n .command('stats')\n .description('View agent statistics')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents stats # View statistics\n $ chanl agents stats --json # Output as JSON`\n )\n .action(handleAgentsStats);\n\n return agents;\n}\n\n/**\n * Format agent status with color\n */\nfunction formatStatus(status?: string): string {\n switch (status) {\n case 'active':\n return chalk.green('active');\n case 'inactive':\n return chalk.gray('inactive');\n case 'error':\n return chalk.red('error');\n case 'training':\n return chalk.cyan('training');\n case 'maintenance':\n return chalk.yellow('maintenance');\n default:\n return chalk.gray(status || 'unknown');\n }\n}\n\n/**\n * Format platform with color\n */\nfunction formatPlatform(platform?: string): string {\n switch (platform) {\n case 'vapi':\n return chalk.blue('vapi');\n case 'elevenlabs':\n return chalk.magenta('elevenlabs');\n case 'custom':\n return chalk.cyan('custom');\n default:\n return chalk.gray(platform || 'unknown');\n }\n}\n\n/**\n * Get agent template for a platform\n */\nfunction getAgentTemplate(platform: string = 'custom'): CreateAgentData {\n const baseTemplate: CreateAgentData = {\n platform: 'custom',\n name: 'My Custom Agent',\n type: 'Voice Assistant',\n status: 'inactive',\n useCase: 'support',\n description: 'A custom AI agent for customer support',\n configuration: {\n prompt: 'You are a helpful customer support agent. Be friendly and professional.',\n model: 'gpt-4o',\n },\n autoAnalysisEnabled: true,\n simulationMode: 'text',\n };\n\n if (platform === 'vapi') {\n return {\n ...baseTemplate,\n platform: 'vapi',\n platformAgentId: 'YOUR_VAPI_ASSISTANT_ID',\n name: 'VAPI Support Agent',\n description: 'VAPI-powered customer support agent',\n phoneNumbers: ['+1234567890'],\n testPhoneNumber: '+1234567890',\n configuration: {\n prompt: 'You are a helpful customer support agent.',\n model: 'gpt-4o',\n voice: 'YOUR_VOICE_ID',\n transcriber: 'deepgram',\n vapi: {\n firstMessage: 'Hello! How can I help you today?',\n webhookUrl: 'https://your-domain.com/webhooks/vapi',\n },\n },\n defaultSimulationChannel: 'websocket',\n simulationMode: 'websocket',\n };\n }\n\n if (platform === 'elevenlabs') {\n return {\n ...baseTemplate,\n platform: 'elevenlabs',\n platformAgentId: 'YOUR_ELEVENLABS_AGENT_ID',\n name: 'ElevenLabs Voice Agent',\n type: 'Text-to-Speech',\n description: 'ElevenLabs-powered voice agent',\n configuration: {\n prompt: 'You are a helpful assistant.',\n voice: 'YOUR_ELEVENLABS_VOICE_ID',\n elevenlabs: {},\n },\n };\n }\n\n return baseTemplate;\n}\n\n/**\n * Handle agents list command\n */\nasync function handleAgentsList(options: {\n platform?: string;\n status?: string;\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching agents...').start();\n\n try {\n const response = await sdk.agents.list({\n provider: options.platform,\n status: options.status,\n limit: parseInt(options.limit, 10),\n page: parseInt(options.page, 10),\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch agents', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { agents, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (agents.length === 0) {\n printInfo('No agents found');\n printInfo(\"Use 'chanl agents sync vapi' to import from VAPI\");\n printInfo(\"Or 'chanl agents create --template' to create a custom agent\");\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Name', 'Platform', 'Status', 'Created'],\n agents.map((a: Agent) => [\n a.id.slice(-12),\n a.name.slice(0, 25),\n formatPlatform(a.provider),\n formatStatus(a.status),\n formatDate(a.createdAt),\n ])\n );\n\n printBlank();\n if (pagination) {\n printInfo(`Total: ${pagination.total} agents (Page ${pagination.page} of ${pagination.totalPages})`);\n }\n } catch (error) {\n spinner.fail('Failed to fetch agents');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents get command\n */\nasync function handleAgentsGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching agent...').start();\n\n try {\n const response = await sdk.agents.get(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch agent', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const agent = response.data;\n printBlank();\n console.log(chalk.bold('Agent Details:'));\n console.log(` ID: ${agent.id}`);\n console.log(` Name: ${agent.name}`);\n console.log(` Platform: ${formatPlatform(agent.provider)}`);\n console.log(` Status: ${formatStatus(agent.status)}`);\n if (agent.providerId) console.log(` Platform ID: ${agent.providerId}`);\n if (agent.description) console.log(` Description: ${agent.description}`);\n console.log(` Created: ${formatDate(agent.createdAt)}`);\n console.log(` Updated: ${formatDate(agent.updatedAt)}`);\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch agent');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents create command\n */\nasync function handleAgentsCreate(options: {\n file?: string;\n template?: string | boolean;\n}): Promise<void> {\n // Handle template output\n if (options.template !== undefined) {\n const platform = typeof options.template === 'string' ? options.template : 'custom';\n const template = getAgentTemplate(platform);\n console.log(JSON.stringify(template, null, 2));\n return;\n }\n\n // Require file for actual creation\n if (!options.file) {\n printError('Missing required option', \"Use '-f <file>' to specify agent data or '--template [platform]' to get a template\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse the file\n let agentData: CreateAgentData;\n try {\n const content = readFileSync(options.file, 'utf-8');\n agentData = JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Failed to read file', message);\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Creating agent...').start();\n\n try {\n const response = await sdk.agents.create(agentData);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to create agent', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const agent = response.data;\n printSuccess(`Agent created: ${agent.name}`);\n printLabel('ID', agent.id);\n printLabel('Platform', agent.provider || 'custom');\n } catch (error) {\n spinner.fail('Failed to create agent');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents update command\n */\nasync function handleAgentsUpdate(\n id: string,\n options: { file?: string; syncToVapi?: boolean }\n): Promise<void> {\n if (!options.file) {\n printError('Missing required option', \"Use '-f <file>' to specify update data\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse the file\n let updateData: Partial<CreateAgentData> & { syncToVapi?: boolean };\n try {\n const content = readFileSync(options.file, 'utf-8');\n updateData = JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Failed to read file', message);\n process.exitCode = 1;\n return;\n }\n\n // Add syncToVapi flag if specified\n if (options.syncToVapi) {\n updateData.syncToVapi = true;\n }\n\n const spinner = ora('Updating agent...').start();\n\n try {\n const response = await sdk.agents.update(id, updateData);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to update agent', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const agent = response.data;\n printSuccess(`Agent updated: ${agent.name}`);\n if (options.syncToVapi) {\n printInfo('Changes synced to VAPI');\n }\n } catch (error) {\n spinner.fail('Failed to update agent');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents delete command\n */\nasync function handleAgentsDelete(\n id: string,\n options: { yes?: boolean; deleteFromIntegration?: boolean }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n if (!options.yes) {\n printInfo(`About to delete agent: ${id}`);\n if (options.deleteFromIntegration) {\n printInfo('This will also delete the agent from the integration platform');\n }\n printInfo(\"Use '--yes' flag to skip this confirmation\");\n }\n\n const spinner = ora('Deleting agent...').start();\n\n try {\n const response = await sdk.agents.delete(id, {\n deleteFromIntegration: options.deleteFromIntegration,\n });\n\n spinner.stop();\n\n if (!response.success) {\n printError('Failed to delete agent', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson({ success: true, deleted: id });\n return;\n }\n\n printSuccess(`Agent deleted: ${id}`);\n } catch (error) {\n spinner.fail('Failed to delete agent');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents sync command\n */\nasync function handleAgentsSync(\n platform: string,\n options: { force?: boolean; clean?: boolean }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const validPlatforms = ['vapi', 'bland', 'twilio'];\n if (!validPlatforms.includes(platform)) {\n printError('Invalid platform', `Valid platforms: ${validPlatforms.join(', ')}`);\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora(`Syncing agents from ${platform}...`).start();\n\n try {\n const response = await sdk.agents.sync(platform as 'vapi' | 'bland' | 'twilio', {\n forceUpdate: options.force,\n cleanBeforeSync: options.clean,\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to sync agents', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const result = response.data as SyncAgentsResult;\n printBlank();\n console.log(chalk.bold('Sync Results:'));\n console.log(` Processed: ${result.processed}`);\n console.log(` Created: ${chalk.green(result.created.toString())}`);\n console.log(` Updated: ${chalk.cyan(result.updated.toString())}`);\n if (result.errors > 0) {\n console.log(` Errors: ${chalk.red(result.errors.toString())}`);\n }\n\n if (result.details && result.details.length > 0) {\n console.log(chalk.bold('\\nDetails:'));\n for (const detail of result.details.slice(0, 10)) {\n const statusColor =\n detail.status === 'created'\n ? chalk.green\n : detail.status === 'updated'\n ? chalk.cyan\n : detail.status === 'error'\n ? chalk.red\n : chalk.gray;\n console.log(` ${detail.name.slice(0, 30)}: ${statusColor(detail.status)}`);\n }\n if (result.details.length > 10) {\n printInfo(`... and ${result.details.length - 10} more`);\n }\n }\n\n printBlank();\n } catch (error) {\n spinner.fail('Failed to sync agents');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents sync-all command\n */\nasync function handleAgentsSyncAll(options: { force?: boolean }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Syncing agents from all platforms...').start();\n\n try {\n const response = await sdk.agents.syncAll({\n forceUpdate: options.force,\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to sync agents', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const result = response.data as SyncAgentsResult;\n printSuccess(result.message || 'Sync completed');\n console.log(` Processed: ${result.processed}`);\n console.log(` Created: ${chalk.green(result.created.toString())}`);\n console.log(` Updated: ${chalk.cyan(result.updated.toString())}`);\n if (result.errors > 0) {\n console.log(` Errors: ${chalk.red(result.errors.toString())}`);\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to sync agents');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents stats command\n */\nasync function handleAgentsImport(options: {\n from: string;\n agentId: string;\n name?: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora(`Importing agent from ${options.from}...`).start();\n\n try {\n const response = await sdk.agents.importFromPlatform({\n platform: options.from,\n externalAgentId: options.agentId,\n ...(options.name ? { name: options.name } : {}),\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Import failed', response.message || 'Could not import agent');\n process.exitCode = 1;\n return;\n }\n\n const agent = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n printBlank();\n printSuccess(`Agent imported from ${options.from}`);\n printBlank();\n printLabel('Name', agent.name);\n printLabel('Chanl ID', agent.id);\n printLabel('Platform', (agent as any).platform || options.from);\n printLabel('External ID', (agent as any).platformAgentId || options.agentId);\n printLabel('Status', agent.status || 'active');\n if (agent.deployments?.length) {\n const dep = agent.deployments[0]!;\n printLabel('Deployment', `${dep.orchestrator} → ${dep.externalId} (${dep.status})`);\n }\n printBlank();\n } catch (error) {\n spinner.fail('Import failed');\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', errorMessage);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents publish command\n */\nasync function handleAgentsPublish(\n agentId: string,\n options: {\n to: string;\n target?: string;\n withMcp?: boolean;\n },\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora(`Publishing agent to ${options.to}...`).start();\n\n try {\n const response = await sdk.agents.publish(agentId, {\n platform: options.to,\n ...(options.target ? { targetExternalId: options.target } : {}),\n ...(options.withMcp ? { includeMcp: true } : {}),\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Publish failed', response.message || 'Could not publish agent');\n process.exitCode = 1;\n return;\n }\n\n const result = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n printBlank();\n printSuccess(`Agent ${result.action} on ${result.platform}`);\n printBlank();\n printLabel('Action', result.action);\n printLabel('Platform', result.platform);\n printLabel('External ID', result.externalId);\n printLabel('Status', result.status);\n if (result.mcpUrl) {\n printLabel('MCP URL', result.mcpUrl);\n }\n printBlank();\n } catch (error) {\n spinner.fail('Publish failed');\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', errorMessage);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents push-mcp command\n */\nasync function handleAgentsPushMcp(\n agentId: string,\n options: {\n to: string;\n target?: string;\n },\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora(`Pushing MCP URL to ${options.to}...`).start();\n\n try {\n const response = await sdk.agents.pushMcp(agentId, {\n platform: options.to,\n ...(options.target ? { targetExternalId: options.target } : {}),\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Push MCP failed', response.message || 'Could not push MCP URL');\n process.exitCode = 1;\n return;\n }\n\n const result = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n printBlank();\n printSuccess(`MCP URL pushed to ${result.platform}`);\n printBlank();\n printLabel('MCP URL', result.mcpUrl);\n printLabel('Platform', result.platform);\n printLabel('External ID', result.externalId);\n printLabel('Status', result.status);\n printBlank();\n } catch (error) {\n spinner.fail('Push MCP failed');\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', errorMessage);\n process.exitCode = 1;\n }\n}\n\nasync function handleAgentsStats(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching statistics...').start();\n\n try {\n const response = await sdk.agents.getStats();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch statistics', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const stats = response.data;\n printBlank();\n console.log(chalk.bold('Agent Statistics:'));\n console.log(chalk.dim('─'.repeat(40)));\n console.log(` Total Agents: ${stats.totalAgents}`);\n console.log(` Average Score: ${stats.avgScore !== null ? `${stats.avgScore.toFixed(1)}%` : '-'}`);\n console.log(` Tool Failures: ${stats.toolFailures}`);\n console.log(` Top Provider: ${stats.topProvider || '-'}`);\n\n if (stats.byPlatform && Object.keys(stats.byPlatform).length > 0) {\n console.log(chalk.bold('\\n By Platform:'));\n for (const [platform, count] of Object.entries(stats.byPlatform)) {\n console.log(` ${formatPlatform(platform)}: ${count}`);\n }\n }\n\n if (stats.byStatus && Object.keys(stats.byStatus).length > 0) {\n console.log(chalk.bold('\\n By Status:'));\n for (const [status, count] of Object.entries(stats.byStatus)) {\n console.log(` ${formatStatus(status)}: ${count}`);\n }\n }\n\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch statistics');\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":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/commands/agents.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { readFileSync } from 'fs';\nimport type { Agent, AgentTemplateSummary, CreateAgentData, SyncAgentsResult } from '@chanl/sdk';\nimport { createSdk } from '../utils/sdk-factory.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 agents command group\n */\nexport function createAgentsCommand(): Command {\n const agents = new Command('agents')\n .description('Manage AI agents (VAPI, ElevenLabs, custom)')\n .addHelpText(\n 'after',\n `\nWhat are Agents?\n Agents are AI-powered voice assistants from various platforms (VAPI, ElevenLabs)\n or custom implementations. They can be tested with scenarios and analyzed with\n scorecards.\n\nQuick Start:\n $ chanl agents list # List all agents\n $ chanl agents get <id> # View agent details\n $ chanl agents sync vapi # Sync from VAPI\n $ chanl agents templates # List provisionable templates\n $ chanl agents create --from-template lead-qualifier --name \"Lead Gen Bot\"\n $ chanl agents create --template vapi # Generate local VAPI scaffold\n $ chanl agents stats # View statistics\n\nWorkflow:\n 1. Sync agents from your platform (vapi, elevenlabs)\n 2. Or create custom agents with 'create -f agent.json'\n 3. Test agents with 'chanl scenarios run <id> --agent <agentId>'\n 4. Analyze results with 'chanl calls analysis <id>'`\n );\n\n // agents list\n agents\n .command('list')\n .description('List all agents')\n .option('-p, --platform <platform>', 'Filter by platform (vapi, elevenlabs, custom)')\n .option('-s, --status <status>', 'Filter by status (active, inactive)')\n .option('-l, --limit <number>', 'Number of items per page', '20')\n .option('--page <number>', 'Page number', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents list # List all agents\n $ chanl agents list --platform vapi # Filter by platform\n $ chanl agents list --status active # Only active agents\n $ chanl agents list --json # Output as JSON`\n )\n .action(handleAgentsList);\n\n // agents get <id>\n agents\n .command('get <id>')\n .description('Get agent details')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents get abc123 # Get agent details\n $ chanl agents get abc123 --json # Output as JSON`\n )\n .action(handleAgentsGet);\n\n // agents templates\n agents\n .command('templates')\n .description('List registry templates you can provision an agent from')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents templates # List registry templates\n $ chanl agents templates --json # Output as JSON\n\nProvision one with:\n $ chanl agents create --from-template lead-qualifier --name \"My Agent\"`\n )\n .action(handleAgentsTemplates);\n\n // agents create\n agents\n .command('create')\n .description('Create a new agent')\n .option('-f, --file <path>', 'Path to JSON file with agent data')\n .option('--template [platform]', 'Output a local scaffold JSON (vapi, elevenlabs, custom) — no server call')\n .option('--from-template <templateId>', \"Provision from a registry template (see 'chanl agents templates')\")\n .option('-n, --name <name>', 'Agent name (used with --from-template)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents create --from-template lead-qualifier --name \"Lead Gen Bot\"\n # Provision from registry template\n $ chanl agents create --template vapi > agent.json # VAPI scaffold JSON (local, no server call)\n $ chanl agents create --template custom > agent.json # Custom scaffold JSON\n $ chanl agents create -f agent.json # Create from file\n\n'--from-template' creates a real, configured agent via the platform's template\nregistry (run 'chanl agents templates' to see what's available). '--template'\njust prints a local JSON scaffold to fill in yourself.`\n )\n .action(handleAgentsCreate);\n\n // agents update <id>\n agents\n .command('update <id>')\n .description('Update an existing agent')\n .option('-f, --file <path>', 'Path to JSON file with update data')\n .option('--sync-to-vapi', 'Sync changes back to VAPI platform')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents update abc123 -f updates.json\n $ chanl agents update abc123 -f updates.json --sync-to-vapi`\n )\n .action(handleAgentsUpdate);\n\n // agents delete <id>\n agents\n .command('delete <id>')\n .description('Delete an agent')\n .option('-y, --yes', 'Skip confirmation prompt')\n .option('--delete-from-integration', 'Also delete from platform (VAPI, etc.)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents delete abc123\n $ chanl agents delete abc123 --delete-from-integration`\n )\n .action(handleAgentsDelete);\n\n // agents sync <platform>\n agents\n .command('sync <platform>')\n .description('Sync agents from a platform (vapi, bland, twilio)')\n .option('-f, --force', 'Force update existing agents')\n .option('--clean', 'Delete all existing agents for this platform before sync')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents sync vapi # Sync from VAPI\n $ chanl agents sync vapi --force # Force update all\n $ chanl agents sync vapi --clean # Clean sync (delete first)`\n )\n .action(handleAgentsSync);\n\n // agents sync-all\n agents\n .command('sync-all')\n .description('Sync agents from all configured platforms')\n .option('-f, --force', 'Force update existing agents')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents sync-all # Sync from all platforms\n $ chanl agents sync-all --force # Force update all`\n )\n .action(handleAgentsSyncAll);\n\n // agents import\n agents\n .command('import')\n .description('Import a specific agent from a third-party platform')\n .requiredOption('--from <platform>', 'Source platform (vapi, retell, bland)')\n .requiredOption('--agent-id <id>', 'External agent ID on the source platform')\n .option('-n, --name <name>', 'Override the agent name')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents import --from vapi --agent-id asst_abc123\n $ chanl agents import --from retell --agent-id ret_xyz --name \"My Agent\"\n $ chanl agents import --from vapi --agent-id asst_abc --json`\n )\n .action(handleAgentsImport);\n\n // agents publish\n agents\n .command('publish <agent-id>')\n .description('Publish an agent to a third-party platform')\n .requiredOption('--to <platform>', 'Target platform (vapi, retell, bland)')\n .option('--target <ext-id>', 'External agent ID to update (omit to create new)')\n .option('--with-mcp', 'Include MCP URL for tool access')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents publish agent_123 --to vapi\n $ chanl agents publish agent_123 --to vapi --with-mcp\n $ chanl agents publish agent_123 --to vapi --target ext_456\n $ chanl agents publish agent_123 --to vapi --json`\n )\n .action(handleAgentsPublish);\n\n // agents push-mcp\n agents\n .command('push-mcp <agent-id>')\n .description('Push MCP URL to a third-party agent for tool access')\n .requiredOption('--to <platform>', 'Target platform (vapi, retell, bland)')\n .option('--target <ext-id>', 'External agent ID (omit to use default)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents push-mcp agent_123 --to vapi\n $ chanl agents push-mcp agent_123 --to vapi --target ext_456\n $ chanl agents push-mcp agent_123 --to vapi --json`\n )\n .action(handleAgentsPushMcp);\n\n // agents stats\n agents\n .command('stats')\n .description('View agent statistics')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl agents stats # View statistics\n $ chanl agents stats --json # Output as JSON`\n )\n .action(handleAgentsStats);\n\n return agents;\n}\n\n/**\n * Format agent status with color\n */\nfunction formatStatus(status?: string): string {\n switch (status) {\n case 'active':\n return chalk.green('active');\n case 'inactive':\n return chalk.gray('inactive');\n case 'error':\n return chalk.red('error');\n case 'training':\n return chalk.cyan('training');\n case 'maintenance':\n return chalk.yellow('maintenance');\n default:\n return chalk.gray(status || 'unknown');\n }\n}\n\n/**\n * Format platform with color\n */\nfunction formatPlatform(platform?: string): string {\n switch (platform) {\n case 'vapi':\n return chalk.blue('vapi');\n case 'elevenlabs':\n return chalk.magenta('elevenlabs');\n case 'custom':\n return chalk.cyan('custom');\n default:\n return chalk.gray(platform || 'unknown');\n }\n}\n\n/**\n * Get agent template for a platform\n */\nfunction getAgentTemplate(platform: string = 'custom'): CreateAgentData {\n const baseTemplate: CreateAgentData = {\n platform: 'custom',\n name: 'My Custom Agent',\n type: 'Voice Assistant',\n status: 'inactive',\n useCase: 'support',\n description: 'A custom AI agent for customer support',\n configuration: {\n prompt: 'You are a helpful customer support agent. Be friendly and professional.',\n model: 'gpt-4o',\n },\n autoAnalysisEnabled: true,\n simulationMode: 'text',\n };\n\n if (platform === 'vapi') {\n return {\n ...baseTemplate,\n platform: 'vapi',\n platformAgentId: 'YOUR_VAPI_ASSISTANT_ID',\n name: 'VAPI Support Agent',\n description: 'VAPI-powered customer support agent',\n phoneNumbers: ['+1234567890'],\n testPhoneNumber: '+1234567890',\n configuration: {\n prompt: 'You are a helpful customer support agent.',\n model: 'gpt-4o',\n voice: 'YOUR_VOICE_ID',\n transcriber: 'deepgram',\n vapi: {\n firstMessage: 'Hello! How can I help you today?',\n webhookUrl: 'https://your-domain.com/webhooks/vapi',\n },\n },\n defaultSimulationChannel: 'websocket',\n simulationMode: 'websocket',\n };\n }\n\n if (platform === 'elevenlabs') {\n return {\n ...baseTemplate,\n platform: 'elevenlabs',\n platformAgentId: 'YOUR_ELEVENLABS_AGENT_ID',\n name: 'ElevenLabs Voice Agent',\n type: 'Text-to-Speech',\n description: 'ElevenLabs-powered voice agent',\n configuration: {\n prompt: 'You are a helpful assistant.',\n voice: 'YOUR_ELEVENLABS_VOICE_ID',\n elevenlabs: {},\n },\n };\n }\n\n return baseTemplate;\n}\n\n/**\n * Handle agents list command\n */\nasync function handleAgentsList(options: {\n platform?: string;\n status?: string;\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching agents...').start();\n\n try {\n const response = await sdk.agents.list({\n provider: options.platform,\n status: options.status,\n limit: parseInt(options.limit, 10),\n page: parseInt(options.page, 10),\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch agents', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { agents, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (agents.length === 0) {\n printInfo('No agents found');\n printInfo(\"Use 'chanl agents sync vapi' to import from VAPI\");\n printInfo(\"Or 'chanl agents create --template' to create a custom agent\");\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Name', 'Platform', 'Status', 'Created'],\n agents.map((a: Agent) => [\n a.id.slice(-12),\n a.name.slice(0, 25),\n formatPlatform(a.provider),\n formatStatus(a.status),\n formatDate(a.createdAt),\n ])\n );\n\n printBlank();\n if (pagination) {\n printInfo(`Total: ${pagination.total} agents (Page ${pagination.page} of ${pagination.totalPages})`);\n }\n } catch (error) {\n spinner.fail('Failed to fetch agents');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents get command\n */\nasync function handleAgentsGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching agent...').start();\n\n try {\n const response = await sdk.agents.get(id);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch agent', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const agent = response.data;\n printBlank();\n console.log(chalk.bold('Agent Details:'));\n console.log(` ID: ${agent.id}`);\n console.log(` Name: ${agent.name}`);\n console.log(` Platform: ${formatPlatform(agent.provider)}`);\n console.log(` Status: ${formatStatus(agent.status)}`);\n if (agent.providerId) console.log(` Platform ID: ${agent.providerId}`);\n if (agent.description) console.log(` Description: ${agent.description}`);\n console.log(` Created: ${formatDate(agent.createdAt)}`);\n console.log(` Updated: ${formatDate(agent.updatedAt)}`);\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch agent');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents templates command\n */\nasync function handleAgentsTemplates(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching templates...').start();\n\n try {\n const response = await sdk.agents.listTemplates();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch templates', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { templates } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (templates.length === 0) {\n printInfo('No templates available');\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Name', 'Version', 'Description'],\n templates.map((t: AgentTemplateSummary) => [t.id, t.name, t.version.toString(), t.description])\n );\n printBlank();\n printInfo('Provision one with: chanl agents create --from-template <id> --name \"My Agent\"');\n } catch (error) {\n spinner.fail('Failed to fetch templates');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle provisioning an agent from a registry template\n * (the --from-template path of `agents create`)\n */\nasync function handleAgentsCreateFromTemplate(templateId: string, name?: string): Promise<void> {\n if (!name) {\n printError('Missing required option', \"Use '-n, --name <name>' together with --from-template\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora(`Provisioning agent from template '${templateId}'...`).start();\n\n try {\n const response = await sdk.agents.createFromTemplate(templateId, { name });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to create agent from template', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const agent = response.data;\n printSuccess(`Agent created from template: ${agent.name}`);\n printLabel('ID', agent.id);\n printLabel('Template', templateId);\n } catch (error) {\n spinner.fail('Failed to create agent from template');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents create command\n */\nasync function handleAgentsCreate(options: {\n file?: string;\n template?: string | boolean;\n fromTemplate?: string;\n name?: string;\n}): Promise<void> {\n // Handle local scaffold output (no server call)\n if (options.template !== undefined) {\n const platform = typeof options.template === 'string' ? options.template : 'custom';\n const template = getAgentTemplate(platform);\n console.log(JSON.stringify(template, null, 2));\n return;\n }\n\n // Handle real provisioning from the platform's template registry\n if (options.fromTemplate) {\n await handleAgentsCreateFromTemplate(options.fromTemplate, options.name);\n return;\n }\n\n // Require file for actual creation\n if (!options.file) {\n printError(\n 'Missing required option',\n \"Use '-f <file>' for agent data, '--from-template <id>' to provision from a registry template, or '--template [platform]' for a local scaffold\"\n );\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse the file\n let agentData: CreateAgentData;\n try {\n const content = readFileSync(options.file, 'utf-8');\n agentData = JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Failed to read file', message);\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Creating agent...').start();\n\n try {\n const response = await sdk.agents.create(agentData);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to create agent', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const agent = response.data;\n printSuccess(`Agent created: ${agent.name}`);\n printLabel('ID', agent.id);\n printLabel('Platform', agent.provider || 'custom');\n } catch (error) {\n spinner.fail('Failed to create agent');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents update command\n */\nasync function handleAgentsUpdate(\n id: string,\n options: { file?: string; syncToVapi?: boolean }\n): Promise<void> {\n if (!options.file) {\n printError('Missing required option', \"Use '-f <file>' to specify update data\");\n process.exitCode = 1;\n return;\n }\n\n const sdk = createSdk();\n if (!sdk) return;\n\n // Read and parse the file\n let updateData: Partial<CreateAgentData> & { syncToVapi?: boolean };\n try {\n const content = readFileSync(options.file, 'utf-8');\n updateData = JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Failed to read file', message);\n process.exitCode = 1;\n return;\n }\n\n // Add syncToVapi flag if specified\n if (options.syncToVapi) {\n updateData.syncToVapi = true;\n }\n\n const spinner = ora('Updating agent...').start();\n\n try {\n const response = await sdk.agents.update(id, updateData);\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to update agent', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const agent = response.data;\n printSuccess(`Agent updated: ${agent.name}`);\n if (options.syncToVapi) {\n printInfo('Changes synced to VAPI');\n }\n } catch (error) {\n spinner.fail('Failed to update agent');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents delete command\n */\nasync function handleAgentsDelete(\n id: string,\n options: { yes?: boolean; deleteFromIntegration?: boolean }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n if (!options.yes) {\n printInfo(`About to delete agent: ${id}`);\n if (options.deleteFromIntegration) {\n printInfo('This will also delete the agent from the integration platform');\n }\n printInfo(\"Use '--yes' flag to skip this confirmation\");\n }\n\n const spinner = ora('Deleting agent...').start();\n\n try {\n const response = await sdk.agents.delete(id, {\n deleteFromIntegration: options.deleteFromIntegration,\n });\n\n spinner.stop();\n\n if (!response.success) {\n printError('Failed to delete agent', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson({ success: true, deleted: id });\n return;\n }\n\n printSuccess(`Agent deleted: ${id}`);\n } catch (error) {\n spinner.fail('Failed to delete agent');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents sync command\n */\nasync function handleAgentsSync(\n platform: string,\n options: { force?: boolean; clean?: boolean }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const validPlatforms = ['vapi', 'bland', 'twilio'];\n if (!validPlatforms.includes(platform)) {\n printError('Invalid platform', `Valid platforms: ${validPlatforms.join(', ')}`);\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora(`Syncing agents from ${platform}...`).start();\n\n try {\n const response = await sdk.agents.sync(platform as 'vapi' | 'bland' | 'twilio', {\n forceUpdate: options.force,\n cleanBeforeSync: options.clean,\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to sync agents', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const result = response.data as SyncAgentsResult;\n printBlank();\n console.log(chalk.bold('Sync Results:'));\n console.log(` Processed: ${result.processed}`);\n console.log(` Created: ${chalk.green(result.created.toString())}`);\n console.log(` Updated: ${chalk.cyan(result.updated.toString())}`);\n if (result.errors > 0) {\n console.log(` Errors: ${chalk.red(result.errors.toString())}`);\n }\n\n if (result.details && result.details.length > 0) {\n console.log(chalk.bold('\\nDetails:'));\n for (const detail of result.details.slice(0, 10)) {\n const statusColor =\n detail.status === 'created'\n ? chalk.green\n : detail.status === 'updated'\n ? chalk.cyan\n : detail.status === 'error'\n ? chalk.red\n : chalk.gray;\n console.log(` ${detail.name.slice(0, 30)}: ${statusColor(detail.status)}`);\n }\n if (result.details.length > 10) {\n printInfo(`... and ${result.details.length - 10} more`);\n }\n }\n\n printBlank();\n } catch (error) {\n spinner.fail('Failed to sync agents');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents sync-all command\n */\nasync function handleAgentsSyncAll(options: { force?: boolean }): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Syncing agents from all platforms...').start();\n\n try {\n const response = await sdk.agents.syncAll({\n forceUpdate: options.force,\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to sync agents', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const result = response.data as SyncAgentsResult;\n printSuccess(result.message || 'Sync completed');\n console.log(` Processed: ${result.processed}`);\n console.log(` Created: ${chalk.green(result.created.toString())}`);\n console.log(` Updated: ${chalk.cyan(result.updated.toString())}`);\n if (result.errors > 0) {\n console.log(` Errors: ${chalk.red(result.errors.toString())}`);\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to sync agents');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents stats command\n */\nasync function handleAgentsImport(options: {\n from: string;\n agentId: string;\n name?: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora(`Importing agent from ${options.from}...`).start();\n\n try {\n const response = await sdk.agents.importFromPlatform({\n platform: options.from,\n externalAgentId: options.agentId,\n ...(options.name ? { name: options.name } : {}),\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Import failed', response.message || 'Could not import agent');\n process.exitCode = 1;\n return;\n }\n\n const agent = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n printBlank();\n printSuccess(`Agent imported from ${options.from}`);\n printBlank();\n printLabel('Name', agent.name);\n printLabel('Chanl ID', agent.id);\n printLabel('Platform', (agent as any).platform || options.from);\n printLabel('External ID', (agent as any).platformAgentId || options.agentId);\n printLabel('Status', agent.status || 'active');\n if (agent.deployments?.length) {\n const dep = agent.deployments[0]!;\n printLabel('Deployment', `${dep.orchestrator} → ${dep.externalId} (${dep.status})`);\n }\n printBlank();\n } catch (error) {\n spinner.fail('Import failed');\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', errorMessage);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents publish command\n */\nasync function handleAgentsPublish(\n agentId: string,\n options: {\n to: string;\n target?: string;\n withMcp?: boolean;\n },\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora(`Publishing agent to ${options.to}...`).start();\n\n try {\n const response = await sdk.agents.publish(agentId, {\n platform: options.to,\n ...(options.target ? { targetExternalId: options.target } : {}),\n ...(options.withMcp ? { includeMcp: true } : {}),\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Publish failed', response.message || 'Could not publish agent');\n process.exitCode = 1;\n return;\n }\n\n const result = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n printBlank();\n printSuccess(`Agent ${result.action} on ${result.platform}`);\n printBlank();\n printLabel('Action', result.action);\n printLabel('Platform', result.platform);\n printLabel('External ID', result.externalId);\n printLabel('Status', result.status);\n if (result.mcpUrl) {\n printLabel('MCP URL', result.mcpUrl);\n }\n printBlank();\n } catch (error) {\n spinner.fail('Publish failed');\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', errorMessage);\n process.exitCode = 1;\n }\n}\n\n/**\n * Handle agents push-mcp command\n */\nasync function handleAgentsPushMcp(\n agentId: string,\n options: {\n to: string;\n target?: string;\n },\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora(`Pushing MCP URL to ${options.to}...`).start();\n\n try {\n const response = await sdk.agents.pushMcp(agentId, {\n platform: options.to,\n ...(options.target ? { targetExternalId: options.target } : {}),\n });\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Push MCP failed', response.message || 'Could not push MCP URL');\n process.exitCode = 1;\n return;\n }\n\n const result = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n printBlank();\n printSuccess(`MCP URL pushed to ${result.platform}`);\n printBlank();\n printLabel('MCP URL', result.mcpUrl);\n printLabel('Platform', result.platform);\n printLabel('External ID', result.externalId);\n printLabel('Status', result.status);\n printBlank();\n } catch (error) {\n spinner.fail('Push MCP failed');\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', errorMessage);\n process.exitCode = 1;\n }\n}\n\nasync function handleAgentsStats(): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching statistics...').start();\n\n try {\n const response = await sdk.agents.getStats();\n\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch statistics', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const stats = response.data;\n printBlank();\n console.log(chalk.bold('Agent Statistics:'));\n console.log(chalk.dim('─'.repeat(40)));\n console.log(` Total Agents: ${stats.totalAgents}`);\n console.log(` Average Score: ${stats.avgScore !== null ? `${stats.avgScore.toFixed(1)}%` : '-'}`);\n console.log(` Tool Failures: ${stats.toolFailures}`);\n console.log(` Top Provider: ${stats.topProvider || '-'}`);\n\n if (stats.byPlatform && Object.keys(stats.byPlatform).length > 0) {\n console.log(chalk.bold('\\n By Platform:'));\n for (const [platform, count] of Object.entries(stats.byPlatform)) {\n console.log(` ${formatPlatform(platform)}: ${count}`);\n }\n }\n\n if (stats.byStatus && Object.keys(stats.byStatus).length > 0) {\n console.log(chalk.bold('\\n By Status:'));\n for (const [status, count] of Object.entries(stats.byStatus)) {\n console.log(` ${formatStatus(status)}: ${count}`);\n }\n }\n\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch statistics');\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/commands/chat.js
CHANGED
|
@@ -17,8 +17,8 @@ function createChatCommand() {
|
|
|
17
17
|
`
|
|
18
18
|
What is Chat?
|
|
19
19
|
Chat lets you test an AI agent via text in your terminal. It creates a session
|
|
20
|
-
|
|
21
|
-
transcription, billing, and evaluation.
|
|
20
|
+
on the Chanl platform, which manages the full lifecycle including
|
|
21
|
+
transcription, billing, and post-chat evaluation.
|
|
22
22
|
|
|
23
23
|
Modes:
|
|
24
24
|
Interactive (default): Opens a prompt loop \u2014 type messages, see agent responses.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/chat.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { createInterface } from 'node:readline';\nimport type { ChanlSDK, ToolCall } from '@chanl/sdk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport {\n printError,\n printSuccess,\n printInfo,\n printBlank,\n isJsonOutput,\n printJson,\n} from '../utils/output.js';\n\n/**\n * Create the chat command\n */\nexport function createChatCommand(): Command {\n const chat = new Command('chat')\n .description('Start an interactive chat session with an agent')\n .argument('<agent-id>', 'ID of the agent to chat with')\n .option('-m, --message <text>', 'Send a single message and exit')\n .option('-s, --stream', 'Enable streaming responses (real-time text)')\n .option('-w, --workspace <id>', 'Workspace ID override')\n .addHelpText(\n 'after',\n `\nWhat is Chat?\n Chat lets you test an AI agent via text in your terminal. It creates a session\n through interactions-service which manages the full lifecycle including\n transcription, billing, and evaluation.\n\nModes:\n Interactive (default): Opens a prompt loop — type messages, see agent responses.\n Type 'exit', 'quit', or press Ctrl+C to end.\n\n Single message: Send one message with --message, print response, exit.\n\nStreaming:\n Use --stream for real-time text output. Text appears as the agent generates it.\n Note: streaming responses do not include tool call metadata.\n\nExamples:\n $ chanl chat abc123 # Interactive chat\n $ chanl chat abc123 --stream # Interactive with streaming\n $ chanl chat abc123 --message \"Hello\" # Single message mode\n $ chanl chat abc123 --message \"Hi\" --stream # Single message, streamed\n $ chanl chat abc123 --message \"Hi\" --json # Single message, JSON output\n $ chanl chat abc123 --workspace ws_456 # Override workspace`\n )\n .action(handleChat);\n\n return chat;\n}\n\n/**\n * Handle the chat command\n */\nasync function handleChat(\n agentId: string,\n options: { message?: string; stream?: boolean; workspace?: string },\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n if (options.message) {\n await handleSingleMessage(sdk, agentId, options.message, options.stream);\n } else {\n await handleInteractiveChat(sdk, agentId, options.stream);\n }\n}\n\n/**\n * Single message mode: create session, send message, print response, end session\n * Uses SDK LiveChat for session management\n */\nasync function handleSingleMessage(\n sdk: ChanlSDK,\n agentId: string,\n message: string,\n stream?: boolean,\n): Promise<void> {\n const spinner = ora('Connecting to agent...').start();\n\n try {\n const chat = await sdk.chat.session(agentId);\n spinner.text = 'Sending message...';\n\n try {\n if (stream && !isJsonOutput()) {\n // Streaming mode: show text as it arrives\n spinner.stop();\n printBlank();\n console.log(chalk.dim('You >'), message);\n process.stdout.write(chalk.cyan('Agent > '));\n\n const reply = await chat.send(message, {\n stream: true,\n onChunk: (delta) => process.stdout.write(delta),\n });\n\n // Newline after streamed text\n console.log();\n if (reply.latencyMs) {\n printBlank();\n printInfo(`Response time: ${reply.latencyMs}ms`);\n }\n printBlank();\n } else {\n // Non-streaming or JSON mode\n const reply = await chat.send(message);\n spinner.stop();\n\n if (isJsonOutput()) {\n printJson({\n sessionId: chat.sessionId,\n agentId,\n message,\n response: reply.message,\n toolCalls: reply.toolCalls,\n latencyMs: reply.latencyMs,\n });\n } else {\n printBlank();\n console.log(chalk.dim('You >'), message);\n if (reply.toolCalls?.length) {\n console.log(chalk.dim(' Tools:'));\n printToolCalls(reply.toolCalls);\n }\n console.log(chalk.cyan('Agent >'), reply.message);\n if (reply.latencyMs) {\n printBlank();\n printInfo(`Response time: ${reply.latencyMs}ms`);\n }\n printBlank();\n }\n }\n } finally {\n await chat.end();\n }\n } catch (error) {\n spinner.fail('Chat failed');\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', errorMessage);\n process.exitCode = 1;\n }\n}\n\n/**\n * Interactive mode: readline prompt loop with agent\n * Uses SDK LiveChat for session management\n */\nasync function handleInteractiveChat(\n sdk: ChanlSDK,\n agentId: string,\n stream?: boolean,\n): Promise<void> {\n const spinner = ora('Connecting to agent...').start();\n\n try {\n const chat = await sdk.chat.session(agentId);\n const agentName = chat.agentName || 'Agent';\n spinner.succeed(`Connected to ${agentName}${stream ? ' (streaming)' : ''}`);\n printInfo(\"Type 'exit' or 'quit' to end the session. Ctrl+C also works.\");\n printBlank();\n\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const prompt = (): void => {\n rl.question(chalk.bold('You > '), async (input) => {\n const trimmed = input.trim();\n\n if (!trimmed) {\n prompt();\n return;\n }\n\n if (trimmed.toLowerCase() === 'exit' || trimmed.toLowerCase() === 'quit') {\n await endSessionCleanly(chat);\n rl.close();\n return;\n }\n\n try {\n if (stream) {\n // Streaming: show text character-by-character\n process.stdout.write(chalk.cyan('Agent > '));\n const reply = await chat.send(trimmed, {\n stream: true,\n onChunk: (delta) => process.stdout.write(delta),\n });\n console.log(); // newline after stream\n if (reply.latencyMs) {\n printInfo(`${reply.latencyMs}ms`);\n }\n } else {\n const reply = await chat.send(trimmed);\n if (reply.toolCalls?.length) {\n console.log(chalk.dim(' Tools:'));\n printToolCalls(reply.toolCalls);\n }\n console.log(chalk.cyan('Agent >'), reply.message);\n }\n printBlank();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Send failed', errorMessage);\n printBlank();\n }\n\n prompt();\n });\n };\n\n // Handle Ctrl+C gracefully\n const handleSigint = async (): Promise<void> => {\n printBlank();\n await endSessionCleanly(chat);\n rl.close();\n process.exit(0);\n };\n\n rl.on('SIGINT', () => {\n void handleSigint();\n });\n\n rl.on('close', () => {\n // Readline closed (e.g., piped input ended)\n });\n\n prompt();\n } catch (error) {\n spinner.fail('Failed to connect');\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', errorMessage);\n process.exitCode = 1;\n }\n}\n\n/**\n * Display tool calls in a readable format\n */\nfunction printToolCalls(toolCalls: ToolCall[]): void {\n for (const tc of toolCalls) {\n const statusIcon =\n tc.status === 'success'\n ? chalk.green('✓')\n : tc.status === 'error'\n ? chalk.red('✗')\n : tc.status === 'timeout'\n ? chalk.yellow('⏱')\n : chalk.dim('…');\n const duration = tc.durationMs ? chalk.dim(` (${tc.durationMs}ms)`) : '';\n const params = Object.keys(tc.parameters).length\n ? chalk.dim(` ${JSON.stringify(tc.parameters)}`)\n : '';\n\n console.log(` ${statusIcon} ${chalk.yellow(tc.name)}${params}${duration}`);\n\n if (tc.status === 'error' && tc.error) {\n console.log(` ${chalk.red(tc.error.message)}`);\n }\n }\n}\n\n/**\n * End a chat session with user feedback\n */\nasync function endSessionCleanly(\n chat: { end: () => Promise<void> },\n): Promise<void> {\n try {\n await chat.end();\n printSuccess('Session ended');\n } catch {\n printInfo('Session closed');\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/commands/chat.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport chalk from 'chalk';\nimport { createInterface } from 'node:readline';\nimport type { ChanlSDK, ToolCall } from '@chanl/sdk';\nimport { createSdk } from '../utils/sdk-factory.js';\nimport {\n printError,\n printSuccess,\n printInfo,\n printBlank,\n isJsonOutput,\n printJson,\n} from '../utils/output.js';\n\n/**\n * Create the chat command\n */\nexport function createChatCommand(): Command {\n const chat = new Command('chat')\n .description('Start an interactive chat session with an agent')\n .argument('<agent-id>', 'ID of the agent to chat with')\n .option('-m, --message <text>', 'Send a single message and exit')\n .option('-s, --stream', 'Enable streaming responses (real-time text)')\n .option('-w, --workspace <id>', 'Workspace ID override')\n .addHelpText(\n 'after',\n `\nWhat is Chat?\n Chat lets you test an AI agent via text in your terminal. It creates a session\n on the Chanl platform, which manages the full lifecycle including\n transcription, billing, and post-chat evaluation.\n\nModes:\n Interactive (default): Opens a prompt loop — type messages, see agent responses.\n Type 'exit', 'quit', or press Ctrl+C to end.\n\n Single message: Send one message with --message, print response, exit.\n\nStreaming:\n Use --stream for real-time text output. Text appears as the agent generates it.\n Note: streaming responses do not include tool call metadata.\n\nExamples:\n $ chanl chat abc123 # Interactive chat\n $ chanl chat abc123 --stream # Interactive with streaming\n $ chanl chat abc123 --message \"Hello\" # Single message mode\n $ chanl chat abc123 --message \"Hi\" --stream # Single message, streamed\n $ chanl chat abc123 --message \"Hi\" --json # Single message, JSON output\n $ chanl chat abc123 --workspace ws_456 # Override workspace`\n )\n .action(handleChat);\n\n return chat;\n}\n\n/**\n * Handle the chat command\n */\nasync function handleChat(\n agentId: string,\n options: { message?: string; stream?: boolean; workspace?: string },\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n if (options.message) {\n await handleSingleMessage(sdk, agentId, options.message, options.stream);\n } else {\n await handleInteractiveChat(sdk, agentId, options.stream);\n }\n}\n\n/**\n * Single message mode: create session, send message, print response, end session\n * Uses SDK LiveChat for session management\n */\nasync function handleSingleMessage(\n sdk: ChanlSDK,\n agentId: string,\n message: string,\n stream?: boolean,\n): Promise<void> {\n const spinner = ora('Connecting to agent...').start();\n\n try {\n const chat = await sdk.chat.session(agentId);\n spinner.text = 'Sending message...';\n\n try {\n if (stream && !isJsonOutput()) {\n // Streaming mode: show text as it arrives\n spinner.stop();\n printBlank();\n console.log(chalk.dim('You >'), message);\n process.stdout.write(chalk.cyan('Agent > '));\n\n const reply = await chat.send(message, {\n stream: true,\n onChunk: (delta) => process.stdout.write(delta),\n });\n\n // Newline after streamed text\n console.log();\n if (reply.latencyMs) {\n printBlank();\n printInfo(`Response time: ${reply.latencyMs}ms`);\n }\n printBlank();\n } else {\n // Non-streaming or JSON mode\n const reply = await chat.send(message);\n spinner.stop();\n\n if (isJsonOutput()) {\n printJson({\n sessionId: chat.sessionId,\n agentId,\n message,\n response: reply.message,\n toolCalls: reply.toolCalls,\n latencyMs: reply.latencyMs,\n });\n } else {\n printBlank();\n console.log(chalk.dim('You >'), message);\n if (reply.toolCalls?.length) {\n console.log(chalk.dim(' Tools:'));\n printToolCalls(reply.toolCalls);\n }\n console.log(chalk.cyan('Agent >'), reply.message);\n if (reply.latencyMs) {\n printBlank();\n printInfo(`Response time: ${reply.latencyMs}ms`);\n }\n printBlank();\n }\n }\n } finally {\n await chat.end();\n }\n } catch (error) {\n spinner.fail('Chat failed');\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', errorMessage);\n process.exitCode = 1;\n }\n}\n\n/**\n * Interactive mode: readline prompt loop with agent\n * Uses SDK LiveChat for session management\n */\nasync function handleInteractiveChat(\n sdk: ChanlSDK,\n agentId: string,\n stream?: boolean,\n): Promise<void> {\n const spinner = ora('Connecting to agent...').start();\n\n try {\n const chat = await sdk.chat.session(agentId);\n const agentName = chat.agentName || 'Agent';\n spinner.succeed(`Connected to ${agentName}${stream ? ' (streaming)' : ''}`);\n printInfo(\"Type 'exit' or 'quit' to end the session. Ctrl+C also works.\");\n printBlank();\n\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const prompt = (): void => {\n rl.question(chalk.bold('You > '), async (input) => {\n const trimmed = input.trim();\n\n if (!trimmed) {\n prompt();\n return;\n }\n\n if (trimmed.toLowerCase() === 'exit' || trimmed.toLowerCase() === 'quit') {\n await endSessionCleanly(chat);\n rl.close();\n return;\n }\n\n try {\n if (stream) {\n // Streaming: show text character-by-character\n process.stdout.write(chalk.cyan('Agent > '));\n const reply = await chat.send(trimmed, {\n stream: true,\n onChunk: (delta) => process.stdout.write(delta),\n });\n console.log(); // newline after stream\n if (reply.latencyMs) {\n printInfo(`${reply.latencyMs}ms`);\n }\n } else {\n const reply = await chat.send(trimmed);\n if (reply.toolCalls?.length) {\n console.log(chalk.dim(' Tools:'));\n printToolCalls(reply.toolCalls);\n }\n console.log(chalk.cyan('Agent >'), reply.message);\n }\n printBlank();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Send failed', errorMessage);\n printBlank();\n }\n\n prompt();\n });\n };\n\n // Handle Ctrl+C gracefully\n const handleSigint = async (): Promise<void> => {\n printBlank();\n await endSessionCleanly(chat);\n rl.close();\n process.exit(0);\n };\n\n rl.on('SIGINT', () => {\n void handleSigint();\n });\n\n rl.on('close', () => {\n // Readline closed (e.g., piped input ended)\n });\n\n prompt();\n } catch (error) {\n spinner.fail('Failed to connect');\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', errorMessage);\n process.exitCode = 1;\n }\n}\n\n/**\n * Display tool calls in a readable format\n */\nfunction printToolCalls(toolCalls: ToolCall[]): void {\n for (const tc of toolCalls) {\n const statusIcon =\n tc.status === 'success'\n ? chalk.green('✓')\n : tc.status === 'error'\n ? chalk.red('✗')\n : tc.status === 'timeout'\n ? chalk.yellow('⏱')\n : chalk.dim('…');\n const duration = tc.durationMs ? chalk.dim(` (${tc.durationMs}ms)`) : '';\n const params = Object.keys(tc.parameters).length\n ? chalk.dim(` ${JSON.stringify(tc.parameters)}`)\n : '';\n\n console.log(` ${statusIcon} ${chalk.yellow(tc.name)}${params}${duration}`);\n\n if (tc.status === 'error' && tc.error) {\n console.log(` ${chalk.red(tc.error.message)}`);\n }\n }\n}\n\n/**\n * End a chat session with user feedback\n */\nasync function endSessionCleanly(\n chat: { end: () => Promise<void> },\n): Promise<void> {\n try {\n await chat.end();\n printSuccess('Session ended');\n } catch {\n printInfo('Session closed');\n }\n}\n"],"mappings":"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","names":[]}
|