@bty/customer-service-cli 0.1.9 → 0.1.11
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/bin.js +120 -15
- package/package.json +3 -3
package/dist/bin.js
CHANGED
|
@@ -66,10 +66,8 @@ function outputInfo(message) {
|
|
|
66
66
|
process.stderr.write(message + "\n");
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
// src/
|
|
70
|
-
import
|
|
71
|
-
|
|
72
|
-
// src/utils/credentials.ts
|
|
69
|
+
// src/utils/update-checker.ts
|
|
70
|
+
import https from "https";
|
|
73
71
|
import fs2 from "fs";
|
|
74
72
|
import path2 from "path";
|
|
75
73
|
|
|
@@ -150,13 +148,109 @@ function initLocalConfig() {
|
|
|
150
148
|
return filePath;
|
|
151
149
|
}
|
|
152
150
|
|
|
151
|
+
// src/utils/update-checker.ts
|
|
152
|
+
var CACHE_FILENAME = "update-check.json";
|
|
153
|
+
var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
154
|
+
var REQUEST_TIMEOUT_MS = 3e3;
|
|
155
|
+
var PACKAGE_NAME = "@bty/customer-service-cli";
|
|
156
|
+
var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
157
|
+
function getCachePath() {
|
|
158
|
+
return path2.join(getConfigDir(), CACHE_FILENAME);
|
|
159
|
+
}
|
|
160
|
+
function readCache() {
|
|
161
|
+
try {
|
|
162
|
+
const content = fs2.readFileSync(getCachePath(), "utf-8");
|
|
163
|
+
return JSON.parse(content);
|
|
164
|
+
} catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function writeCache(cache) {
|
|
169
|
+
const dir = getConfigDir();
|
|
170
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
171
|
+
fs2.writeFileSync(getCachePath(), JSON.stringify(cache, null, 2));
|
|
172
|
+
}
|
|
173
|
+
function compareSemver(current, latest) {
|
|
174
|
+
const parse = (v) => v.replace(/^v/, "").split(".").map(Number);
|
|
175
|
+
const a = parse(current);
|
|
176
|
+
const b = parse(latest);
|
|
177
|
+
for (let i = 0; i < 3; i++) {
|
|
178
|
+
const av = a[i] ?? 0;
|
|
179
|
+
const bv = b[i] ?? 0;
|
|
180
|
+
if (av < bv) return -1;
|
|
181
|
+
if (av > bv) return 1;
|
|
182
|
+
}
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
function fetchLatestVersion() {
|
|
186
|
+
return new Promise((resolve, reject) => {
|
|
187
|
+
const req = https.get(REGISTRY_URL, { timeout: REQUEST_TIMEOUT_MS }, (res) => {
|
|
188
|
+
if (res.statusCode !== 200) {
|
|
189
|
+
reject(new Error(`HTTP ${res.statusCode}`));
|
|
190
|
+
res.resume();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
let body = "";
|
|
194
|
+
res.setEncoding("utf-8");
|
|
195
|
+
res.on("data", (chunk) => {
|
|
196
|
+
body += chunk;
|
|
197
|
+
});
|
|
198
|
+
res.on("end", () => {
|
|
199
|
+
try {
|
|
200
|
+
const data = JSON.parse(body);
|
|
201
|
+
if (data.version) {
|
|
202
|
+
resolve(data.version);
|
|
203
|
+
} else {
|
|
204
|
+
reject(new Error("No version field in response"));
|
|
205
|
+
}
|
|
206
|
+
} catch {
|
|
207
|
+
reject(new Error("Invalid JSON response"));
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
req.on("error", reject);
|
|
212
|
+
req.on("timeout", () => {
|
|
213
|
+
req.destroy();
|
|
214
|
+
reject(new Error("Request timeout"));
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
async function checkForUpdate(currentVersion) {
|
|
219
|
+
if (process.env.CS_CLI_NO_UPDATE_CHECK === "1") {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const cache = readCache();
|
|
224
|
+
const now = Date.now();
|
|
225
|
+
if (cache && now - cache.lastCheckedAt < CHECK_INTERVAL_MS) {
|
|
226
|
+
return compareSemver(currentVersion, cache.latestVersion) < 0 ? formatUpdateMessage(currentVersion, cache.latestVersion) : null;
|
|
227
|
+
}
|
|
228
|
+
const latestVersion = await fetchLatestVersion();
|
|
229
|
+
writeCache({ latestVersion, lastCheckedAt: now });
|
|
230
|
+
return compareSemver(currentVersion, latestVersion) < 0 ? formatUpdateMessage(currentVersion, latestVersion) : null;
|
|
231
|
+
} catch {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function formatUpdateMessage(current, latest) {
|
|
236
|
+
return `
|
|
237
|
+
\u26A0 \u53D1\u73B0\u65B0\u7248\u672C ${PACKAGE_NAME}@${latest}\uFF08\u5F53\u524D ${current}\uFF09
|
|
238
|
+
\u8FD0\u884C pnpm add -g ${PACKAGE_NAME} \u5347\u7EA7
|
|
239
|
+
`;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// src/client/auth-api.ts
|
|
243
|
+
import CryptoJS from "crypto-js";
|
|
244
|
+
|
|
153
245
|
// src/utils/credentials.ts
|
|
246
|
+
import fs3 from "fs";
|
|
247
|
+
import path3 from "path";
|
|
154
248
|
function getCredentialsPath() {
|
|
155
|
-
return
|
|
249
|
+
return path3.join(getConfigDir(), "credentials.json");
|
|
156
250
|
}
|
|
157
251
|
function readCredentials() {
|
|
158
252
|
try {
|
|
159
|
-
const content =
|
|
253
|
+
const content = fs3.readFileSync(getCredentialsPath(), "utf-8");
|
|
160
254
|
return JSON.parse(content);
|
|
161
255
|
} catch {
|
|
162
256
|
return null;
|
|
@@ -164,12 +258,12 @@ function readCredentials() {
|
|
|
164
258
|
}
|
|
165
259
|
function writeCredentials(creds) {
|
|
166
260
|
const dir = getConfigDir();
|
|
167
|
-
|
|
168
|
-
|
|
261
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
262
|
+
fs3.writeFileSync(getCredentialsPath(), JSON.stringify(creds, null, 2));
|
|
169
263
|
}
|
|
170
264
|
function clearCredentials() {
|
|
171
265
|
try {
|
|
172
|
-
|
|
266
|
+
fs3.unlinkSync(getCredentialsPath());
|
|
173
267
|
} catch {
|
|
174
268
|
}
|
|
175
269
|
}
|
|
@@ -194,7 +288,7 @@ function toExitCode(err) {
|
|
|
194
288
|
return 1;
|
|
195
289
|
}
|
|
196
290
|
function createRequest(globalTimeout) {
|
|
197
|
-
return async function request(baseUrl,
|
|
291
|
+
return async function request(baseUrl, path4, options) {
|
|
198
292
|
const headers = {
|
|
199
293
|
"Content-Type": "application/json",
|
|
200
294
|
...options.headers
|
|
@@ -215,7 +309,7 @@ function createRequest(globalTimeout) {
|
|
|
215
309
|
if (workspaceId) {
|
|
216
310
|
headers["workspace-id"] = workspaceId;
|
|
217
311
|
}
|
|
218
|
-
let url = `${baseUrl}${
|
|
312
|
+
let url = `${baseUrl}${path4}`;
|
|
219
313
|
if (options.query) {
|
|
220
314
|
const params = new URLSearchParams();
|
|
221
315
|
for (const [key, value] of Object.entries(options.query)) {
|
|
@@ -495,7 +589,7 @@ async function updateAgent(configId, data) {
|
|
|
495
589
|
}
|
|
496
590
|
|
|
497
591
|
// src/utils/data-parser.ts
|
|
498
|
-
import
|
|
592
|
+
import fs4 from "fs";
|
|
499
593
|
function parseDataOption(value) {
|
|
500
594
|
if (!value) {
|
|
501
595
|
throw new Error("Data option cannot be empty");
|
|
@@ -507,7 +601,7 @@ function parseDataOption(value) {
|
|
|
507
601
|
}
|
|
508
602
|
let content;
|
|
509
603
|
try {
|
|
510
|
-
content =
|
|
604
|
+
content = fs4.readFileSync(filePath, "utf-8");
|
|
511
605
|
} catch {
|
|
512
606
|
throw new Error(`Cannot read file: ${filePath}`);
|
|
513
607
|
}
|
|
@@ -971,13 +1065,18 @@ function registerIssueCommand(program2) {
|
|
|
971
1065
|
process.exit(toExitCode(err));
|
|
972
1066
|
}
|
|
973
1067
|
});
|
|
974
|
-
issue.command("create").description("\u624B\u52A8\u521B\u5EFA\u5DE5\u5355").requiredOption("--title <title>", "\u5DE5\u5355\u6807\u9898\uFF08\u7B80\u8981\u63CF\u8FF0\u95EE\u9898\uFF09").requiredOption("--content <content>", "\u5DE5\u5355\u5185\u5BB9\uFF08\u8BE6\u7EC6\u63CF\u8FF0\u95EE\u9898\u73B0\u8C61\u548C\u671F\u671B\u7ED3\u679C\uFF09").option("--priority <priority>", "\u4F18\u5148\u7EA7: critical | high | medium | low").option("--tags <tags...>", "\u6807\u7B7E\uFF08\u591A\u4E2A\u7A7A\u683C\u5206\u9694\uFF0C\u7528\u4E8E\u5206\u7C7B\u7B5B\u9009\uFF09").action(async (opts) => {
|
|
1068
|
+
issue.command("create").description("\u624B\u52A8\u521B\u5EFA\u5DE5\u5355").requiredOption("--title <title>", "\u5DE5\u5355\u6807\u9898\uFF08\u7B80\u8981\u63CF\u8FF0\u95EE\u9898\uFF09").requiredOption("--content <content>", "\u5DE5\u5355\u5185\u5BB9\uFF08\u8BE6\u7EC6\u63CF\u8FF0\u95EE\u9898\u73B0\u8C61\u548C\u671F\u671B\u7ED3\u679C\uFF09").option("--priority <priority>", "\u4F18\u5148\u7EA7: critical | high | medium | low").option("--tags <tags...>", "\u6807\u7B7E\uFF08\u591A\u4E2A\u7A7A\u683C\u5206\u9694\uFF0C\u7528\u4E8E\u5206\u7C7B\u7B5B\u9009\uFF09").option("--conversation-id <id>", "\u5173\u8054\u7684\u4F1A\u8BDD ID").option("--record-id <id>", "\u5173\u8054\u7684\u6D88\u606F\u8BB0\u5F55 ID").option("--workspace-id <id>", "\u5DE5\u4F5C\u7A7A\u95F4 ID\uFF08\u9ED8\u8BA4\u4ECE\u73AF\u5883\u53D8\u91CF\u8BFB\u53D6\uFF09").option("--source-type <type>", "\u6765\u6E90\u7C7B\u578B").option("--source-data <json>", "\u6765\u6E90\u6570\u636E\uFF08JSON \u5B57\u7B26\u4E32\uFF09").action(async (opts) => {
|
|
975
1069
|
try {
|
|
976
1070
|
const data = await createIssue({
|
|
977
1071
|
title: opts.title,
|
|
978
1072
|
content: opts.content,
|
|
979
1073
|
priority: opts.priority,
|
|
980
|
-
tags: opts.tags
|
|
1074
|
+
tags: opts.tags,
|
|
1075
|
+
conversation_id: opts.conversationId,
|
|
1076
|
+
record_id: opts.recordId,
|
|
1077
|
+
workspace_id: opts.workspaceId,
|
|
1078
|
+
source_type: opts.sourceType,
|
|
1079
|
+
source_data: opts.sourceData ? JSON.parse(opts.sourceData) : void 0
|
|
981
1080
|
});
|
|
982
1081
|
formatOutput({ success: true, data }, program2.opts().table);
|
|
983
1082
|
} catch (err) {
|
|
@@ -1919,6 +2018,12 @@ program.hook("preAction", (thisCommand) => {
|
|
|
1919
2018
|
setRuntimeWorkspaceId(opts.workspace);
|
|
1920
2019
|
}
|
|
1921
2020
|
});
|
|
2021
|
+
program.hook("postAction", async () => {
|
|
2022
|
+
const message = await checkForUpdate(version);
|
|
2023
|
+
if (message) {
|
|
2024
|
+
outputInfo(message);
|
|
2025
|
+
}
|
|
2026
|
+
});
|
|
1922
2027
|
registerAuthCommand(program);
|
|
1923
2028
|
registerConfigCommand(program);
|
|
1924
2029
|
registerWorkspaceCommand(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bty/customer-service-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "AI Customer Service CLI - Agent friendly",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/bin.js",
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"cli-table3": "^0.6.0",
|
|
15
15
|
"commander": "^14.0.0",
|
|
16
|
-
"crypto-js": "^4.
|
|
16
|
+
"crypto-js": "^4.1.1"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@types/crypto-js": "^4.
|
|
19
|
+
"@types/crypto-js": "^4.1.1",
|
|
20
20
|
"@types/node": "22.18.8",
|
|
21
21
|
"tsup": "^8.0.0",
|
|
22
22
|
"tsx": "^4.0.0",
|