@chanl/cli 2.0.4 → 3.1.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__/cli-p0-scenarios.test.d.ts +2 -0
- package/dist/__tests__/cli-p0-scenarios.test.js +123 -0
- package/dist/__tests__/cli-p0-scenarios.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/cli.js +8 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/agents.js +194 -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/customers.d.ts +8 -0
- package/dist/commands/customers.js +289 -0
- package/dist/commands/customers.js.map +1 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.js +7 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/memory.js +134 -1
- package/dist/commands/memory.js.map +1 -1
- package/dist/commands/messaging.d.ts +12 -0
- package/dist/commands/messaging.js +208 -0
- package/dist/commands/messaging.js.map +1 -0
- package/dist/commands/prompts.js +148 -1
- package/dist/commands/prompts.js.map +1 -1
- package/dist/commands/scenarios.js +121 -0
- package/dist/commands/scenarios.js.map +1 -1
- package/dist/commands/scorecards.js +3 -3
- package/dist/commands/scorecards.js.map +1 -1
- package/dist/commands/whatsapp.d.ts +8 -0
- package/dist/commands/whatsapp.js +332 -0
- package/dist/commands/whatsapp.js.map +1 -0
- 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,289 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
import { createSdk } from "../utils/sdk-factory.js";
|
|
5
|
+
import {
|
|
6
|
+
printError,
|
|
7
|
+
printSuccess,
|
|
8
|
+
printInfo,
|
|
9
|
+
printBlank,
|
|
10
|
+
printSimpleTable,
|
|
11
|
+
printLabel,
|
|
12
|
+
isJsonOutput,
|
|
13
|
+
printJson,
|
|
14
|
+
formatDate
|
|
15
|
+
} from "../utils/output.js";
|
|
16
|
+
function createCustomersCommand() {
|
|
17
|
+
const customers = new Command("customers").description("Manage the customer record \u2014 the profile every conversation attaches to").addHelpText(
|
|
18
|
+
"after",
|
|
19
|
+
`
|
|
20
|
+
What are Customers?
|
|
21
|
+
The customer record is Chanl's primary surface: every conversation
|
|
22
|
+
(voice, chat, WhatsApp) attaches to a customer. Records carry contact
|
|
23
|
+
info, sourced attributes, and channel identities.
|
|
24
|
+
|
|
25
|
+
Quick Start:
|
|
26
|
+
$ chanl customers list # List customers
|
|
27
|
+
$ chanl customers list --search dean # Free-text search
|
|
28
|
+
$ chanl customers get <id> # View a record
|
|
29
|
+
$ chanl customers create --phone +14155551234 --first-name Dean
|
|
30
|
+
$ chanl customers resolve --phone +14155551234 # Find-or-create by phone/email
|
|
31
|
+
$ chanl customers delete <id> # Delete a record`
|
|
32
|
+
);
|
|
33
|
+
customers.command("list").description("List customers in the workspace").option("-s, --search <text>", "Free-text search (name, phone, email)").option("--limit <number>", "Number of items per page", "20").option("-p, --page <number>", "Page number", "1").addHelpText(
|
|
34
|
+
"after",
|
|
35
|
+
`
|
|
36
|
+
Examples:
|
|
37
|
+
$ chanl customers list # First page
|
|
38
|
+
$ chanl customers list --search dean # Search by name/phone/email
|
|
39
|
+
$ chanl customers list --json # Output as JSON`
|
|
40
|
+
).action(handleCustomersList);
|
|
41
|
+
customers.command("get <id>").description("Get customer details").action(handleCustomersGet);
|
|
42
|
+
customers.command("create").description("Create a customer").option("--first-name <name>", "First name").option("--last-name <name>", "Last name").option("--email <email>", "Email address").option("--phone <e164>", "Phone number in E.164 format (+14155551234)").option("--agent <agentId>", "Route this customer to a specific agent").option("-f, --file <path>", "Path to JSON file with customer data (overrides flags)").addHelpText(
|
|
43
|
+
"after",
|
|
44
|
+
`
|
|
45
|
+
Examples:
|
|
46
|
+
$ chanl customers create --phone +14155551234 --first-name Dean
|
|
47
|
+
$ chanl customers create -f customer.json`
|
|
48
|
+
).action(handleCustomersCreate);
|
|
49
|
+
customers.command("update <id>").description("Update a customer").option("--first-name <name>", "First name").option("--last-name <name>", "Last name").option("--email <email>", "Email address").option("--phone <e164>", "Phone number in E.164 format").option("--agent <agentId>", "Route this customer to a specific agent").option("-f, --file <path>", "Path to JSON file with fields to update (overrides flags)").action(handleCustomersUpdate);
|
|
50
|
+
customers.command("resolve").description("Resolve by phone/email \u2014 returns existing customer or creates one").option("--phone <e164>", "Phone number in E.164 format").option("--email <email>", "Email address").option("--first-name <name>", "First name (used only on create)").option("--last-name <name>", "Last name (used only on create)").addHelpText(
|
|
51
|
+
"after",
|
|
52
|
+
`
|
|
53
|
+
Examples:
|
|
54
|
+
$ chanl customers resolve --phone +14155551234
|
|
55
|
+
$ chanl customers resolve --email dean@example.com --first-name Dean`
|
|
56
|
+
).action(handleCustomersResolve);
|
|
57
|
+
customers.command("delete <id>").description("Delete a customer").action(handleCustomersDelete);
|
|
58
|
+
return customers;
|
|
59
|
+
}
|
|
60
|
+
function customerDisplayName(c) {
|
|
61
|
+
const name = [c.firstName, c.lastName].filter(Boolean).join(" ");
|
|
62
|
+
return name || c.displayName || "-";
|
|
63
|
+
}
|
|
64
|
+
async function handleCustomersList(options) {
|
|
65
|
+
const sdk = createSdk();
|
|
66
|
+
if (!sdk) return;
|
|
67
|
+
const spinner = ora("Fetching customers...").start();
|
|
68
|
+
try {
|
|
69
|
+
const response = await sdk.customers.list({
|
|
70
|
+
search: options.search,
|
|
71
|
+
limit: parseInt(options.limit, 10),
|
|
72
|
+
page: parseInt(options.page, 10)
|
|
73
|
+
});
|
|
74
|
+
spinner.stop();
|
|
75
|
+
if (!response.success || !response.data) {
|
|
76
|
+
printError("Failed to fetch customers", response.message);
|
|
77
|
+
process.exitCode = 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const { data: customers, pagination } = response.data;
|
|
81
|
+
if (isJsonOutput()) {
|
|
82
|
+
printJson(response.data);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (customers.length === 0) {
|
|
86
|
+
printInfo("No customers found");
|
|
87
|
+
printInfo("Use 'chanl customers create' or 'chanl customers resolve' to add one");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
printBlank();
|
|
91
|
+
printSimpleTable(
|
|
92
|
+
["ID", "Name", "Phone", "Email", "Type", "Last seen"],
|
|
93
|
+
customers.map((c) => [
|
|
94
|
+
c.id.slice(-12),
|
|
95
|
+
customerDisplayName(c).slice(0, 24),
|
|
96
|
+
c.phoneNumber || "-",
|
|
97
|
+
(c.email || "-").slice(0, 28),
|
|
98
|
+
c.contactType || "-",
|
|
99
|
+
c.lastSeenAt ? formatDate(c.lastSeenAt) : "-"
|
|
100
|
+
])
|
|
101
|
+
);
|
|
102
|
+
printBlank();
|
|
103
|
+
if (pagination) {
|
|
104
|
+
printInfo(`Total: ${pagination.total} customers (Page ${pagination.page} of ${pagination.totalPages})`);
|
|
105
|
+
}
|
|
106
|
+
} catch (error) {
|
|
107
|
+
spinner.fail("Failed to fetch customers");
|
|
108
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
109
|
+
printError("Error", message);
|
|
110
|
+
process.exitCode = 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async function handleCustomersGet(id) {
|
|
114
|
+
const sdk = createSdk();
|
|
115
|
+
if (!sdk) return;
|
|
116
|
+
const spinner = ora("Fetching customer...").start();
|
|
117
|
+
try {
|
|
118
|
+
const response = await sdk.customers.get(id);
|
|
119
|
+
spinner.stop();
|
|
120
|
+
if (!response.success || !response.data) {
|
|
121
|
+
printError("Failed to fetch customer", response.message);
|
|
122
|
+
process.exitCode = 1;
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (isJsonOutput()) {
|
|
126
|
+
printJson(response.data);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const c = response.data;
|
|
130
|
+
printBlank();
|
|
131
|
+
printLabel("ID", c.id);
|
|
132
|
+
printLabel("Name", customerDisplayName(c));
|
|
133
|
+
printLabel("Phone", c.phoneNumber || "-");
|
|
134
|
+
printLabel("Email", c.email || "-");
|
|
135
|
+
printLabel("Type", c.contactType || "-");
|
|
136
|
+
printLabel("Agent override", c.agentId || "-");
|
|
137
|
+
printLabel("Language", c.language || "-");
|
|
138
|
+
printLabel("Last seen", c.lastSeenAt ? formatDate(c.lastSeenAt) : "-");
|
|
139
|
+
printLabel("Created", formatDate(c.createdAt));
|
|
140
|
+
if (c.customAttributes && Object.keys(c.customAttributes).length > 0) {
|
|
141
|
+
printBlank();
|
|
142
|
+
printInfo("Attributes:");
|
|
143
|
+
for (const [key, value] of Object.entries(c.customAttributes)) {
|
|
144
|
+
printLabel(` ${key}`, typeof value === "object" ? JSON.stringify(value) : String(value));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
printBlank();
|
|
148
|
+
} catch (error) {
|
|
149
|
+
spinner.fail("Failed to fetch customer");
|
|
150
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
151
|
+
printError("Error", message);
|
|
152
|
+
process.exitCode = 1;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function customerDataFromOptions(options) {
|
|
156
|
+
if (options.file) {
|
|
157
|
+
return JSON.parse(readFileSync(options.file, "utf-8"));
|
|
158
|
+
}
|
|
159
|
+
const data = {};
|
|
160
|
+
if (options.firstName) data.firstName = options.firstName;
|
|
161
|
+
if (options.lastName) data.lastName = options.lastName;
|
|
162
|
+
if (options.email) data.email = options.email;
|
|
163
|
+
if (options.phone) data.phoneNumber = options.phone;
|
|
164
|
+
if (options.agent) data.agentId = options.agent;
|
|
165
|
+
return data;
|
|
166
|
+
}
|
|
167
|
+
async function handleCustomersCreate(options) {
|
|
168
|
+
const sdk = createSdk();
|
|
169
|
+
if (!sdk) return;
|
|
170
|
+
const data = customerDataFromOptions(options);
|
|
171
|
+
if (Object.keys(data).length === 0) {
|
|
172
|
+
printError("Nothing to create", "Provide --phone/--email/--first-name flags or -f <file>");
|
|
173
|
+
process.exitCode = 1;
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const spinner = ora("Creating customer...").start();
|
|
177
|
+
try {
|
|
178
|
+
const response = await sdk.customers.create(data);
|
|
179
|
+
spinner.stop();
|
|
180
|
+
if (!response.success || !response.data) {
|
|
181
|
+
printError("Failed to create customer", response.message);
|
|
182
|
+
process.exitCode = 1;
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (isJsonOutput()) {
|
|
186
|
+
printJson(response.data);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
printSuccess(`Customer created: ${response.data.id}`);
|
|
190
|
+
printInfo(`View it: chanl customers get ${response.data.id}`);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
spinner.fail("Failed to create customer");
|
|
193
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
194
|
+
printError("Error", message);
|
|
195
|
+
process.exitCode = 1;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async function handleCustomersUpdate(id, options) {
|
|
199
|
+
const sdk = createSdk();
|
|
200
|
+
if (!sdk) return;
|
|
201
|
+
const data = customerDataFromOptions(options);
|
|
202
|
+
if (Object.keys(data).length === 0) {
|
|
203
|
+
printError("Nothing to update", "Provide flags or -f <file>");
|
|
204
|
+
process.exitCode = 1;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const spinner = ora("Updating customer...").start();
|
|
208
|
+
try {
|
|
209
|
+
const response = await sdk.customers.update(id, data);
|
|
210
|
+
spinner.stop();
|
|
211
|
+
if (!response.success || !response.data) {
|
|
212
|
+
printError("Failed to update customer", response.message);
|
|
213
|
+
process.exitCode = 1;
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (isJsonOutput()) {
|
|
217
|
+
printJson(response.data);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
printSuccess(`Customer updated: ${id}`);
|
|
221
|
+
} catch (error) {
|
|
222
|
+
spinner.fail("Failed to update customer");
|
|
223
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
224
|
+
printError("Error", message);
|
|
225
|
+
process.exitCode = 1;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
async function handleCustomersResolve(options) {
|
|
229
|
+
const sdk = createSdk();
|
|
230
|
+
if (!sdk) return;
|
|
231
|
+
if (!options.phone && !options.email) {
|
|
232
|
+
printError("Phone or email required", "Use --phone +E164 or --email");
|
|
233
|
+
process.exitCode = 1;
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const spinner = ora("Resolving customer...").start();
|
|
237
|
+
try {
|
|
238
|
+
const response = await sdk.customers.resolve({
|
|
239
|
+
phone: options.phone,
|
|
240
|
+
email: options.email,
|
|
241
|
+
firstName: options.firstName,
|
|
242
|
+
lastName: options.lastName
|
|
243
|
+
});
|
|
244
|
+
spinner.stop();
|
|
245
|
+
if (!response.success || !response.data) {
|
|
246
|
+
printError("Failed to resolve customer", response.message);
|
|
247
|
+
process.exitCode = 1;
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (isJsonOutput()) {
|
|
251
|
+
printJson(response.data);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const { customer, created } = response.data;
|
|
255
|
+
printSuccess(
|
|
256
|
+
created ? `Customer created: ${customer.id}` : `Existing customer: ${customer.id} (${customerDisplayName(customer)})`
|
|
257
|
+
);
|
|
258
|
+
printInfo(`View it: chanl customers get ${customer.id}`);
|
|
259
|
+
} catch (error) {
|
|
260
|
+
spinner.fail("Failed to resolve customer");
|
|
261
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
262
|
+
printError("Error", message);
|
|
263
|
+
process.exitCode = 1;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
async function handleCustomersDelete(id) {
|
|
267
|
+
const sdk = createSdk();
|
|
268
|
+
if (!sdk) return;
|
|
269
|
+
const spinner = ora("Deleting customer...").start();
|
|
270
|
+
try {
|
|
271
|
+
const response = await sdk.customers.delete(id);
|
|
272
|
+
spinner.stop();
|
|
273
|
+
if (!response.success) {
|
|
274
|
+
printError("Failed to delete customer", response.message);
|
|
275
|
+
process.exitCode = 1;
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
printSuccess(`Customer deleted: ${id}`);
|
|
279
|
+
} catch (error) {
|
|
280
|
+
spinner.fail("Failed to delete customer");
|
|
281
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
282
|
+
printError("Error", message);
|
|
283
|
+
process.exitCode = 1;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
export {
|
|
287
|
+
createCustomersCommand
|
|
288
|
+
};
|
|
289
|
+
//# sourceMappingURL=customers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/customers.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport { readFileSync } from 'fs';\nimport type { Customer, CreateCustomerData } 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 customers command group\n */\nexport function createCustomersCommand(): Command {\n const customers = new Command('customers')\n .description('Manage the customer record — the profile every conversation attaches to')\n .addHelpText(\n 'after',\n `\nWhat are Customers?\n The customer record is Chanl's primary surface: every conversation\n (voice, chat, WhatsApp) attaches to a customer. Records carry contact\n info, sourced attributes, and channel identities.\n\nQuick Start:\n $ chanl customers list # List customers\n $ chanl customers list --search dean # Free-text search\n $ chanl customers get <id> # View a record\n $ chanl customers create --phone +14155551234 --first-name Dean\n $ chanl customers resolve --phone +14155551234 # Find-or-create by phone/email\n $ chanl customers delete <id> # Delete a record`\n );\n\n // customers list\n customers\n .command('list')\n .description('List customers in the workspace')\n .option('-s, --search <text>', 'Free-text search (name, phone, email)')\n .option('--limit <number>', 'Number of items per page', '20')\n .option('-p, --page <number>', 'Page number', '1')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl customers list # First page\n $ chanl customers list --search dean # Search by name/phone/email\n $ chanl customers list --json # Output as JSON`\n )\n .action(handleCustomersList);\n\n // customers get <id>\n customers\n .command('get <id>')\n .description('Get customer details')\n .action(handleCustomersGet);\n\n // customers create\n customers\n .command('create')\n .description('Create a customer')\n .option('--first-name <name>', 'First name')\n .option('--last-name <name>', 'Last name')\n .option('--email <email>', 'Email address')\n .option('--phone <e164>', 'Phone number in E.164 format (+14155551234)')\n .option('--agent <agentId>', 'Route this customer to a specific agent')\n .option('-f, --file <path>', 'Path to JSON file with customer data (overrides flags)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl customers create --phone +14155551234 --first-name Dean\n $ chanl customers create -f customer.json`\n )\n .action(handleCustomersCreate);\n\n // customers update <id>\n customers\n .command('update <id>')\n .description('Update a customer')\n .option('--first-name <name>', 'First name')\n .option('--last-name <name>', 'Last name')\n .option('--email <email>', 'Email address')\n .option('--phone <e164>', 'Phone number in E.164 format')\n .option('--agent <agentId>', 'Route this customer to a specific agent')\n .option('-f, --file <path>', 'Path to JSON file with fields to update (overrides flags)')\n .action(handleCustomersUpdate);\n\n // customers resolve\n customers\n .command('resolve')\n .description('Resolve by phone/email — returns existing customer or creates one')\n .option('--phone <e164>', 'Phone number in E.164 format')\n .option('--email <email>', 'Email address')\n .option('--first-name <name>', 'First name (used only on create)')\n .option('--last-name <name>', 'Last name (used only on create)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ chanl customers resolve --phone +14155551234\n $ chanl customers resolve --email dean@example.com --first-name Dean`\n )\n .action(handleCustomersResolve);\n\n // customers delete <id>\n customers\n .command('delete <id>')\n .description('Delete a customer')\n .action(handleCustomersDelete);\n\n return customers;\n}\n\nfunction customerDisplayName(c: Customer): string {\n const name = [c.firstName, c.lastName].filter(Boolean).join(' ');\n return name || c.displayName || '-';\n}\n\nasync function handleCustomersList(options: {\n search?: string;\n limit: string;\n page: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching customers...').start();\n\n try {\n const response = await sdk.customers.list({\n search: options.search,\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 customers', response.message);\n process.exitCode = 1;\n return;\n }\n\n const { data: customers, pagination } = response.data;\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n if (customers.length === 0) {\n printInfo('No customers found');\n printInfo(\"Use 'chanl customers create' or 'chanl customers resolve' to add one\");\n return;\n }\n\n printBlank();\n printSimpleTable(\n ['ID', 'Name', 'Phone', 'Email', 'Type', 'Last seen'],\n customers.map((c: Customer) => [\n c.id.slice(-12),\n customerDisplayName(c).slice(0, 24),\n c.phoneNumber || '-',\n (c.email || '-').slice(0, 28),\n c.contactType || '-',\n c.lastSeenAt ? formatDate(c.lastSeenAt) : '-',\n ])\n );\n\n printBlank();\n if (pagination) {\n printInfo(`Total: ${pagination.total} customers (Page ${pagination.page} of ${pagination.totalPages})`);\n }\n } catch (error) {\n spinner.fail('Failed to fetch customers');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\nasync function handleCustomersGet(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Fetching customer...').start();\n\n try {\n const response = await sdk.customers.get(id);\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to fetch customer', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const c = response.data;\n printBlank();\n printLabel('ID', c.id);\n printLabel('Name', customerDisplayName(c));\n printLabel('Phone', c.phoneNumber || '-');\n printLabel('Email', c.email || '-');\n printLabel('Type', c.contactType || '-');\n printLabel('Agent override', c.agentId || '-');\n printLabel('Language', c.language || '-');\n printLabel('Last seen', c.lastSeenAt ? formatDate(c.lastSeenAt) : '-');\n printLabel('Created', formatDate(c.createdAt));\n if (c.customAttributes && Object.keys(c.customAttributes).length > 0) {\n printBlank();\n printInfo('Attributes:');\n for (const [key, value] of Object.entries(c.customAttributes)) {\n printLabel(` ${key}`, typeof value === 'object' ? JSON.stringify(value) : String(value));\n }\n }\n printBlank();\n } catch (error) {\n spinner.fail('Failed to fetch customer');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\nfunction customerDataFromOptions(options: {\n firstName?: string;\n lastName?: string;\n email?: string;\n phone?: string;\n agent?: string;\n file?: string;\n}): CreateCustomerData {\n if (options.file) {\n return JSON.parse(readFileSync(options.file, 'utf-8')) as CreateCustomerData;\n }\n const data: CreateCustomerData = {};\n if (options.firstName) data.firstName = options.firstName;\n if (options.lastName) data.lastName = options.lastName;\n if (options.email) data.email = options.email;\n if (options.phone) data.phoneNumber = options.phone;\n if (options.agent) data.agentId = options.agent;\n return data;\n}\n\nasync function handleCustomersCreate(options: {\n firstName?: string;\n lastName?: string;\n email?: string;\n phone?: string;\n agent?: string;\n file?: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const data = customerDataFromOptions(options);\n if (Object.keys(data).length === 0) {\n printError('Nothing to create', 'Provide --phone/--email/--first-name flags or -f <file>');\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Creating customer...').start();\n\n try {\n const response = await sdk.customers.create(data);\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to create customer', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n printSuccess(`Customer created: ${response.data.id}`);\n printInfo(`View it: chanl customers get ${response.data.id}`);\n } catch (error) {\n spinner.fail('Failed to create customer');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\nasync function handleCustomersUpdate(\n id: string,\n options: {\n firstName?: string;\n lastName?: string;\n email?: string;\n phone?: string;\n agent?: string;\n file?: string;\n }\n): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const data = customerDataFromOptions(options);\n if (Object.keys(data).length === 0) {\n printError('Nothing to update', 'Provide flags or -f <file>');\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Updating customer...').start();\n\n try {\n const response = await sdk.customers.update(id, data);\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to update customer', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n printSuccess(`Customer updated: ${id}`);\n } catch (error) {\n spinner.fail('Failed to update customer');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\nasync function handleCustomersResolve(options: {\n phone?: string;\n email?: string;\n firstName?: string;\n lastName?: string;\n}): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n if (!options.phone && !options.email) {\n printError('Phone or email required', 'Use --phone +E164 or --email');\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora('Resolving customer...').start();\n\n try {\n const response = await sdk.customers.resolve({\n phone: options.phone,\n email: options.email,\n firstName: options.firstName,\n lastName: options.lastName,\n });\n spinner.stop();\n\n if (!response.success || !response.data) {\n printError('Failed to resolve customer', response.message);\n process.exitCode = 1;\n return;\n }\n\n if (isJsonOutput()) {\n printJson(response.data);\n return;\n }\n\n const { customer, created } = response.data;\n printSuccess(\n created\n ? `Customer created: ${customer.id}`\n : `Existing customer: ${customer.id} (${customerDisplayName(customer)})`\n );\n printInfo(`View it: chanl customers get ${customer.id}`);\n } catch (error) {\n spinner.fail('Failed to resolve customer');\n const message = error instanceof Error ? error.message : 'Unknown error';\n printError('Error', message);\n process.exitCode = 1;\n }\n}\n\nasync function handleCustomersDelete(id: string): Promise<void> {\n const sdk = createSdk();\n if (!sdk) return;\n\n const spinner = ora('Deleting customer...').start();\n\n try {\n const response = await sdk.customers.delete(id);\n spinner.stop();\n\n if (!response.success) {\n printError('Failed to delete customer', response.message);\n process.exitCode = 1;\n return;\n }\n\n printSuccess(`Customer deleted: ${id}`);\n } catch (error) {\n spinner.fail('Failed to delete customer');\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/index.d.ts
CHANGED
|
@@ -6,6 +6,9 @@ export { createScenariosCommand } from './scenarios.js';
|
|
|
6
6
|
export { createCallCommand } from './call.js';
|
|
7
7
|
export { createCallsCommand } from './calls.js';
|
|
8
8
|
export { createPersonasCommand } from './personas.js';
|
|
9
|
+
export { createCustomersCommand } from './customers.js';
|
|
10
|
+
export { createConversationsCommand, createMessagesCommand } from './messaging.js';
|
|
11
|
+
export { createWhatsAppCommand } from './whatsapp.js';
|
|
9
12
|
export { createAgentsCommand } from './agents.js';
|
|
10
13
|
export { createHealthCommand } from './health.js';
|
|
11
14
|
export { createMcpCommand } from './mcp.js';
|
package/dist/commands/index.js
CHANGED
|
@@ -6,6 +6,9 @@ import { createScenariosCommand } from "./scenarios.js";
|
|
|
6
6
|
import { createCallCommand } from "./call.js";
|
|
7
7
|
import { createCallsCommand } from "./calls.js";
|
|
8
8
|
import { createPersonasCommand } from "./personas.js";
|
|
9
|
+
import { createCustomersCommand } from "./customers.js";
|
|
10
|
+
import { createConversationsCommand, createMessagesCommand } from "./messaging.js";
|
|
11
|
+
import { createWhatsAppCommand } from "./whatsapp.js";
|
|
9
12
|
import { createAgentsCommand } from "./agents.js";
|
|
10
13
|
import { createHealthCommand } from "./health.js";
|
|
11
14
|
import { createMcpCommand } from "./mcp.js";
|
|
@@ -22,18 +25,22 @@ export {
|
|
|
22
25
|
createCallsCommand,
|
|
23
26
|
createChatCommand,
|
|
24
27
|
createConfigCommand,
|
|
28
|
+
createConversationsCommand,
|
|
29
|
+
createCustomersCommand,
|
|
25
30
|
createHealthCommand,
|
|
26
31
|
createKnowledgeCommand,
|
|
27
32
|
createLoginCommand,
|
|
28
33
|
createLogoutCommand,
|
|
29
34
|
createMcpCommand,
|
|
30
35
|
createMemoryCommand,
|
|
36
|
+
createMessagesCommand,
|
|
31
37
|
createPersonasCommand,
|
|
32
38
|
createPromptsCommand,
|
|
33
39
|
createScenariosCommand,
|
|
34
40
|
createScorecardsCommand,
|
|
35
41
|
createToolsCommand,
|
|
36
42
|
createToolsetsCommand,
|
|
43
|
+
createWhatsAppCommand,
|
|
37
44
|
createWorkspacesCommand
|
|
38
45
|
};
|
|
39
46
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/commands/index.ts"],"sourcesContent":["/**\n * Command exports for the Chanl CLI\n */\n\nexport { createAuthCommand, createLoginCommand, createLogoutCommand } from './auth.js';\nexport { createConfigCommand } from './config.js';\nexport { createToolsCommand } from './tools.js';\nexport { createToolsetsCommand } from './toolsets.js';\nexport { createScenariosCommand } from './scenarios.js';\nexport { createCallCommand } from './call.js';\nexport { createCallsCommand } from './calls.js';\nexport { createPersonasCommand } from './personas.js';\nexport { createAgentsCommand } from './agents.js';\nexport { createHealthCommand } from './health.js';\nexport { createMcpCommand } from './mcp.js';\nexport { createScorecardsCommand } from './scorecards.js';\nexport { createKnowledgeCommand } from './knowledge.js';\nexport { createMemoryCommand } from './memory.js';\nexport { createChatCommand } from './chat.js';\nexport { createPromptsCommand } from './prompts.js';\nexport { createWorkspacesCommand } from './workspaces.js';\n"],"mappings":"AAIA,SAAS,mBAAmB,oBAAoB,2BAA2B;AAC3E,SAAS,2BAA2B;AACpC,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,SAAS,8BAA8B;AACvC,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AACpC,SAAS,wBAAwB;AACjC,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AACrC,SAAS,+BAA+B;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/commands/index.ts"],"sourcesContent":["/**\n * Command exports for the Chanl CLI\n */\n\nexport { createAuthCommand, createLoginCommand, createLogoutCommand } from './auth.js';\nexport { createConfigCommand } from './config.js';\nexport { createToolsCommand } from './tools.js';\nexport { createToolsetsCommand } from './toolsets.js';\nexport { createScenariosCommand } from './scenarios.js';\nexport { createCallCommand } from './call.js';\nexport { createCallsCommand } from './calls.js';\nexport { createPersonasCommand } from './personas.js';\nexport { createCustomersCommand } from './customers.js';\nexport { createConversationsCommand, createMessagesCommand } from './messaging.js';\nexport { createWhatsAppCommand } from './whatsapp.js';\nexport { createAgentsCommand } from './agents.js';\nexport { createHealthCommand } from './health.js';\nexport { createMcpCommand } from './mcp.js';\nexport { createScorecardsCommand } from './scorecards.js';\nexport { createKnowledgeCommand } from './knowledge.js';\nexport { createMemoryCommand } from './memory.js';\nexport { createChatCommand } from './chat.js';\nexport { createPromptsCommand } from './prompts.js';\nexport { createWorkspacesCommand } from './workspaces.js';\n"],"mappings":"AAIA,SAAS,mBAAmB,oBAAoB,2BAA2B;AAC3E,SAAS,2BAA2B;AACpC,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,SAAS,8BAA8B;AACvC,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,SAAS,8BAA8B;AACvC,SAAS,4BAA4B,6BAA6B;AAClE,SAAS,6BAA6B;AACtC,SAAS,2BAA2B;AACpC,SAAS,2BAA2B;AACpC,SAAS,wBAAwB;AACjC,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AACvC,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AACrC,SAAS,+BAA+B;","names":[]}
|
package/dist/commands/memory.js
CHANGED
|
@@ -71,15 +71,32 @@ Examples:
|
|
|
71
71
|
$ chanl memory delete 680a1b2c3d4e5f6789012345 # With confirmation
|
|
72
72
|
$ chanl memory delete 680a1b2c3d4e5f6789012345 -y # Skip confirmation`
|
|
73
73
|
).action(handleMemoryDelete);
|
|
74
|
-
memory.command("search").description("Search memories using semantic similarity").option("--entity-type <type>", "Entity type (required): customer, session, agent, conversation").option("--entity-id <id>", "Entity ID (required)").option("--query <text>", "Search query text (required)").option("--agent-id <id>", "Optional agent scope filter").option("-l, --limit <number>", "Maximum results").option("--min-score <number>", "Minimum relevance score (0-1)").addHelpText(
|
|
74
|
+
memory.command("search").description("Search memories using semantic similarity").option("--entity-type <type>", "Entity type (required): customer, session, agent, conversation").option("--entity-id <id>", "Entity ID (required)").option("--query <text>", "Search query text (required)").option("--agent-id <id>", "Optional agent scope filter").option("-l, --limit <number>", "Maximum results").option("--min-score <number>", "Minimum relevance score (0-1)").option("--min-confidence <number>", "Minimum extraction confidence (0-1)").option("--created-after <iso>", "Only memories created at/after this ISO-8601 timestamp").option("--created-before <iso>", "Only memories created at/before this ISO-8601 timestamp").addHelpText(
|
|
75
75
|
"after",
|
|
76
76
|
`
|
|
77
77
|
Examples:
|
|
78
78
|
$ chanl memory search --entity-type customer --entity-id cust_123 --query "email preferences"
|
|
79
79
|
$ chanl memory search --entity-type customer --entity-id cust_123 --query "contact" --limit 5
|
|
80
80
|
$ chanl memory search --entity-type customer --entity-id cust_123 --query "VIP" --min-score 0.8
|
|
81
|
+
$ chanl memory search --entity-type customer --entity-id cust_123 --query "recent" --created-after 2026-05-01T00:00:00Z
|
|
81
82
|
$ chanl memory search --entity-type customer --entity-id cust_123 --query "test" --json`
|
|
82
83
|
).action(handleMemorySearch);
|
|
84
|
+
memory.command("search-global").description("Search ALL memories in the workspace (no entity scope)").option("--query <text>", "Search query text (required)").option("--entity-type <type>", "Optional: narrow to an entity type").option("--agent-id <id>", "Optional agent scope filter").option("--source <source>", "Filter by source: conversation, manual, extraction").option("-l, --limit <number>", "Maximum results").option("--min-score <number>", "Minimum relevance score (0-1)").addHelpText(
|
|
85
|
+
"after",
|
|
86
|
+
`
|
|
87
|
+
Examples:
|
|
88
|
+
$ chanl memory search-global --query "billing preferences"
|
|
89
|
+
$ chanl memory search-global --query "VIP" --entity-type customer --limit 10
|
|
90
|
+
$ chanl memory search-global --query "test" --json`
|
|
91
|
+
).action(handleMemorySearchGlobal);
|
|
92
|
+
memory.command("stats").description("Aggregate memory statistics (totals, by type/source, top-accessed)").option("--entity-type <type>", "Optionally scope stats to an entity type").option("--entity-id <id>", "Optionally scope stats to an entity ID").addHelpText(
|
|
93
|
+
"after",
|
|
94
|
+
`
|
|
95
|
+
Examples:
|
|
96
|
+
$ chanl memory stats # Workspace-wide
|
|
97
|
+
$ chanl memory stats --entity-type customer --entity-id cust_123
|
|
98
|
+
$ chanl memory stats --json`
|
|
99
|
+
).action(handleMemoryStats);
|
|
83
100
|
return memory;
|
|
84
101
|
}
|
|
85
102
|
function truncate(str, maxLen) {
|
|
@@ -336,6 +353,15 @@ async function handleMemorySearch(options) {
|
|
|
336
353
|
if (options.minScore) {
|
|
337
354
|
input.minScore = parseFloat(options.minScore);
|
|
338
355
|
}
|
|
356
|
+
if (options.minConfidence) {
|
|
357
|
+
input.minConfidence = parseFloat(options.minConfidence);
|
|
358
|
+
}
|
|
359
|
+
if (options.createdAfter) {
|
|
360
|
+
input.createdAfter = options.createdAfter;
|
|
361
|
+
}
|
|
362
|
+
if (options.createdBefore) {
|
|
363
|
+
input.createdBefore = options.createdBefore;
|
|
364
|
+
}
|
|
339
365
|
const spinner = ora("Searching memories...").start();
|
|
340
366
|
try {
|
|
341
367
|
const response = await sdk.memory.search(input);
|
|
@@ -374,6 +400,113 @@ async function handleMemorySearch(options) {
|
|
|
374
400
|
process.exitCode = 1;
|
|
375
401
|
}
|
|
376
402
|
}
|
|
403
|
+
async function handleMemorySearchGlobal(options) {
|
|
404
|
+
if (!options.query) {
|
|
405
|
+
printError("Missing required option", "Provide --query");
|
|
406
|
+
printInfo("Run 'chanl memory search-global --help' for usage");
|
|
407
|
+
process.exitCode = 1;
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
const sdk = createSdk();
|
|
411
|
+
if (!sdk) return;
|
|
412
|
+
const input = { query: options.query };
|
|
413
|
+
if (options.entityType) input.entityType = options.entityType;
|
|
414
|
+
if (options.agentId) input.agentId = options.agentId;
|
|
415
|
+
if (options.source) input.source = options.source;
|
|
416
|
+
if (options.limit) input.limit = parseInt(options.limit, 10);
|
|
417
|
+
if (options.minScore) input.minScore = parseFloat(options.minScore);
|
|
418
|
+
const spinner = ora("Searching all memories...").start();
|
|
419
|
+
try {
|
|
420
|
+
const response = await sdk.memory.searchGlobal(input);
|
|
421
|
+
spinner.stop();
|
|
422
|
+
if (!response.success || !response.data) {
|
|
423
|
+
printError("Failed to search memories", response.message);
|
|
424
|
+
process.exitCode = 1;
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
const { memories } = response.data;
|
|
428
|
+
if (isJsonOutput()) {
|
|
429
|
+
printJson({ memories });
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
if (memories.length === 0) {
|
|
433
|
+
printInfo("No matching memories found");
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
printBlank();
|
|
437
|
+
printSimpleTable(
|
|
438
|
+
["ID", "Score", "Content", "Entity Type", "Entity ID"],
|
|
439
|
+
memories.map((m) => [
|
|
440
|
+
truncate(m.id, 12),
|
|
441
|
+
(m.score ?? 0).toFixed(2),
|
|
442
|
+
truncate(m.content, 50),
|
|
443
|
+
m.entityType,
|
|
444
|
+
m.entityId
|
|
445
|
+
])
|
|
446
|
+
);
|
|
447
|
+
printBlank();
|
|
448
|
+
printInfo(`Found ${memories.length} matching memories`);
|
|
449
|
+
} catch (error) {
|
|
450
|
+
spinner.fail("Failed to search memories");
|
|
451
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
452
|
+
printError("Error", message);
|
|
453
|
+
process.exitCode = 1;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
async function handleMemoryStats(options) {
|
|
457
|
+
const sdk = createSdk();
|
|
458
|
+
if (!sdk) return;
|
|
459
|
+
const spinner = ora("Aggregating memory stats...").start();
|
|
460
|
+
try {
|
|
461
|
+
const response = await sdk.memory.stats({
|
|
462
|
+
entityType: options.entityType,
|
|
463
|
+
entityId: options.entityId
|
|
464
|
+
});
|
|
465
|
+
spinner.stop();
|
|
466
|
+
if (!response.success || !response.data) {
|
|
467
|
+
printError("Failed to fetch memory stats", response.message);
|
|
468
|
+
process.exitCode = 1;
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const stats = response.data;
|
|
472
|
+
if (isJsonOutput()) {
|
|
473
|
+
printJson(stats);
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
printBlank();
|
|
477
|
+
printLabel("Total", String(stats.total));
|
|
478
|
+
printLabel("Active", chalk.green(String(stats.active)));
|
|
479
|
+
printLabel("Inactive", String(stats.inactive));
|
|
480
|
+
printLabel("Expired", stats.expired > 0 ? chalk.yellow(String(stats.expired)) : "0");
|
|
481
|
+
printLabel("Avg confidence", stats.avgConfidence.toFixed(3));
|
|
482
|
+
printBlank();
|
|
483
|
+
printInfo("By type:");
|
|
484
|
+
printSimpleTable(
|
|
485
|
+
["Entity Type", "Count"],
|
|
486
|
+
Object.entries(stats.byType).map(([k, v]) => [k, String(v)])
|
|
487
|
+
);
|
|
488
|
+
printBlank();
|
|
489
|
+
printInfo("By source:");
|
|
490
|
+
printSimpleTable(
|
|
491
|
+
["Source", "Count"],
|
|
492
|
+
Object.entries(stats.bySource).map(([k, v]) => [k, String(v)])
|
|
493
|
+
);
|
|
494
|
+
if (stats.topAccessed.length > 0) {
|
|
495
|
+
printBlank();
|
|
496
|
+
printInfo("Top accessed:");
|
|
497
|
+
printSimpleTable(
|
|
498
|
+
["ID", "Access Count", "Content"],
|
|
499
|
+
stats.topAccessed.map((t) => [truncate(t.id, 12), String(t.accessCount), truncate(t.content, 50)])
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
printBlank();
|
|
503
|
+
} catch (error) {
|
|
504
|
+
spinner.fail("Failed to fetch memory stats");
|
|
505
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
506
|
+
printError("Error", message);
|
|
507
|
+
process.exitCode = 1;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
377
510
|
function printMemoryDetails(memory) {
|
|
378
511
|
printLabel("ID", memory.id);
|
|
379
512
|
printLabel("Entity Type", memory.entityType);
|