ccjk 12.0.6 → 12.0.7
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/README.md +14 -0
- package/README.zh-CN.md +13 -0
- package/dist/chunks/api-cli.mjs +1 -1
- package/dist/chunks/ccjk-agents.mjs +3 -2
- package/dist/chunks/ccjk-all.mjs +129 -1764
- package/dist/chunks/ccjk-hooks.mjs +5 -4
- package/dist/chunks/ccjk-mcp.mjs +7 -6
- package/dist/chunks/ccjk-setup.mjs +3 -2
- package/dist/chunks/ccjk-skills.mjs +6 -5
- package/dist/chunks/ccr.mjs +6 -5
- package/dist/chunks/check-updates.mjs +8 -8
- package/dist/chunks/claude-code-config-manager.mjs +1 -1
- package/dist/chunks/claude-code-incremental-manager.mjs +2 -2
- package/dist/chunks/codex-config-switch.mjs +1 -1
- package/dist/chunks/codex-provider-manager.mjs +1 -1
- package/dist/chunks/config-switch.mjs +1 -1
- package/dist/chunks/config.mjs +1 -1
- package/dist/chunks/config2.mjs +1 -1
- package/dist/chunks/config3.mjs +1 -1
- package/dist/chunks/constants.mjs +33 -2
- package/dist/chunks/dashboard.mjs +115 -3
- package/dist/chunks/features.mjs +3 -3
- package/dist/chunks/init.mjs +108 -4
- package/dist/chunks/installer2.mjs +7 -7
- package/dist/chunks/manager.mjs +1048 -0
- package/dist/chunks/mcp-cli.mjs +1 -1
- package/dist/chunks/mcp.mjs +1 -1
- package/dist/chunks/menu.mjs +22 -1
- package/dist/chunks/notification.mjs +5 -2
- package/dist/chunks/package.mjs +1 -1
- package/dist/chunks/quick-provider.mjs +1 -269
- package/dist/chunks/quick-setup.mjs +10 -10
- package/dist/chunks/remote.mjs +4 -1
- package/dist/chunks/simple-config.mjs +1 -1
- package/dist/chunks/skill.mjs +117 -9003
- package/dist/chunks/skill2.mjs +9003 -0
- package/dist/chunks/skills-sync.mjs +536 -55
- package/dist/chunks/skills.mjs +7 -1156
- package/dist/chunks/smart-defaults.mjs +87 -9
- package/dist/chunks/status.mjs +1 -1
- package/dist/chunks/uninstall.mjs +1 -1
- package/dist/chunks/update.mjs +2 -2
- package/dist/chunks/zero-config.mjs +6 -2
- package/dist/cli.mjs +3 -1
- package/dist/i18n/locales/en/cloud.json +40 -0
- package/dist/i18n/locales/zh-CN/cloud.json +40 -0
- package/dist/index.d.mts +2586 -2
- package/dist/index.d.ts +2586 -2
- package/dist/index.mjs +1340 -7
- package/dist/shared/ccjk.B364Fu0N.mjs +1819 -0
- package/dist/shared/ccjk.BtB1e5jm.mjs +171 -0
- package/dist/shared/{ccjk.BnpWvs9V.mjs → ccjk.BwfbSKN2.mjs} +1 -1
- package/dist/shared/{ccjk.AqnXPAzw.mjs → ccjk.C2jHOZVP.mjs} +1 -1
- package/dist/shared/{ccjk.BSYWk9ML.mjs → ccjk.Cjj8SVrn.mjs} +1 -1
- package/dist/shared/ccjk.D6ycHbak.mjs +270 -0
- package/dist/shared/ccjk.D8ZLYSZZ.mjs +299 -0
- package/dist/shared/{ccjk.s7OCVzdd.mjs → ccjk.DS7UESmF.mjs} +2 -1483
- package/dist/shared/{ccjk.BiCrMV5O.mjs → ccjk.DXRAZcix.mjs} +0 -28
- package/dist/shared/ccjk.UIvifqNE.mjs +1486 -0
- package/dist/shared/{ccjk.BDKUdmLk.mjs → ccjk.c-ETfBZ_.mjs} +208 -86
- package/package.json +5 -1
- package/templates/claude-code/common/settings.json +3 -1
|
@@ -3,6 +3,7 @@ import os__default, { homedir } from 'node:os';
|
|
|
3
3
|
import { writeFileAtomic } from '../chunks/fs-operations.mjs';
|
|
4
4
|
import { Buffer } from 'node:buffer';
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
|
+
import { c as createDefaultGateway } from './ccjk.BtB1e5jm.mjs';
|
|
6
7
|
import { j as join } from './ccjk.bQ7Dh1g4.mjs';
|
|
7
8
|
|
|
8
9
|
const TOKEN_PREFIX = "ccjk_";
|
|
@@ -100,14 +101,150 @@ function maskToken(token) {
|
|
|
100
101
|
return `${prefix}***...***${suffix}`;
|
|
101
102
|
}
|
|
102
103
|
|
|
104
|
+
function validateBindRequest(request) {
|
|
105
|
+
const errors = [];
|
|
106
|
+
if (!request.code || typeof request.code !== "string") {
|
|
107
|
+
errors.push("code is required and must be a string");
|
|
108
|
+
} else if (request.code.length < 4) {
|
|
109
|
+
errors.push("code must be at least 4 characters");
|
|
110
|
+
}
|
|
111
|
+
if (!request.deviceInfo || typeof request.deviceInfo !== "object") {
|
|
112
|
+
errors.push("deviceInfo is required and must be an object");
|
|
113
|
+
} else {
|
|
114
|
+
if (!request.deviceInfo.name || typeof request.deviceInfo.name !== "string") {
|
|
115
|
+
errors.push("deviceInfo.name is required and must be a string");
|
|
116
|
+
}
|
|
117
|
+
if (!request.deviceInfo.platform || typeof request.deviceInfo.platform !== "string") {
|
|
118
|
+
errors.push("deviceInfo.platform is required and must be a string");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
valid: errors.length === 0,
|
|
123
|
+
errors
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function validateNotifyRequest(request) {
|
|
127
|
+
const errors = [];
|
|
128
|
+
if (!request.title || typeof request.title !== "string") {
|
|
129
|
+
errors.push("title is required and must be a string");
|
|
130
|
+
} else if (request.title.length > 200) {
|
|
131
|
+
errors.push("title must be 200 characters or less");
|
|
132
|
+
}
|
|
133
|
+
if (!request.body || typeof request.body !== "string") {
|
|
134
|
+
errors.push("body is required and must be a string");
|
|
135
|
+
} else if (request.body.length > 4e3) {
|
|
136
|
+
errors.push("body must be 4000 characters or less");
|
|
137
|
+
}
|
|
138
|
+
if (request.type && !["info", "success", "warning", "error"].includes(request.type)) {
|
|
139
|
+
errors.push("type must be one of: info, success, warning, error");
|
|
140
|
+
}
|
|
141
|
+
if (request.actions) {
|
|
142
|
+
if (!Array.isArray(request.actions)) {
|
|
143
|
+
errors.push("actions must be an array");
|
|
144
|
+
} else {
|
|
145
|
+
request.actions.forEach((action, index) => {
|
|
146
|
+
if (!action.id || typeof action.id !== "string") {
|
|
147
|
+
errors.push(`actions[${index}].id is required and must be a string`);
|
|
148
|
+
}
|
|
149
|
+
if (!action.label || typeof action.label !== "string") {
|
|
150
|
+
errors.push(`actions[${index}].label is required and must be a string`);
|
|
151
|
+
}
|
|
152
|
+
if (!action.value || typeof action.value !== "string") {
|
|
153
|
+
errors.push(`actions[${index}].value is required and must be a string`);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
valid: errors.length === 0,
|
|
160
|
+
errors
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function validateBindResponse(response) {
|
|
164
|
+
const errors = [];
|
|
165
|
+
if (typeof response.success !== "boolean") {
|
|
166
|
+
errors.push("success is required and must be a boolean");
|
|
167
|
+
}
|
|
168
|
+
if (response.success) {
|
|
169
|
+
if (!response.data) {
|
|
170
|
+
errors.push("data is required when success is true");
|
|
171
|
+
} else {
|
|
172
|
+
if (!response.data.deviceToken || typeof response.data.deviceToken !== "string") {
|
|
173
|
+
errors.push("data.deviceToken is required and must be a string");
|
|
174
|
+
}
|
|
175
|
+
if (!response.data.deviceId || typeof response.data.deviceId !== "string") {
|
|
176
|
+
errors.push("data.deviceId is required and must be a string");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
if (!response.error || typeof response.error !== "string") {
|
|
181
|
+
errors.push("error is required when success is false");
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
valid: errors.length === 0,
|
|
186
|
+
errors
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function validateNotifyResponse(response) {
|
|
190
|
+
const errors = [];
|
|
191
|
+
if (typeof response.success !== "boolean") {
|
|
192
|
+
errors.push("success is required and must be a boolean");
|
|
193
|
+
}
|
|
194
|
+
if (response.success) {
|
|
195
|
+
if (!response.data) {
|
|
196
|
+
errors.push("data is required when success is true");
|
|
197
|
+
} else {
|
|
198
|
+
if (!response.data.notificationId || typeof response.data.notificationId !== "string") {
|
|
199
|
+
errors.push("data.notificationId is required and must be a string");
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
if (!response.error || typeof response.error !== "string") {
|
|
204
|
+
errors.push("error is required when success is false");
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
valid: errors.length === 0,
|
|
209
|
+
errors
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function validatePollResponse(response) {
|
|
213
|
+
const errors = [];
|
|
214
|
+
if (typeof response.success !== "boolean") {
|
|
215
|
+
errors.push("success is required and must be a boolean");
|
|
216
|
+
}
|
|
217
|
+
if (response.success) {
|
|
218
|
+
if (!response.data) {
|
|
219
|
+
errors.push("data is required when success is true");
|
|
220
|
+
} else if (response.data.reply !== null) {
|
|
221
|
+
const reply = response.data.reply;
|
|
222
|
+
if (!reply.content || typeof reply.content !== "string") {
|
|
223
|
+
errors.push("data.reply.content is required and must be a string");
|
|
224
|
+
}
|
|
225
|
+
if (!reply.timestamp || typeof reply.timestamp !== "string") {
|
|
226
|
+
errors.push("data.reply.timestamp is required and must be a string");
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
if (!response.error || typeof response.error !== "string") {
|
|
231
|
+
errors.push("error is required when success is false");
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
valid: errors.length === 0,
|
|
236
|
+
errors
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
103
240
|
const CLOUD_API_BASE_URL = "https://api.claudehome.cn";
|
|
104
|
-
const DEFAULT_TIMEOUT = 3e4;
|
|
105
241
|
const POLL_TIMEOUT = 6e4;
|
|
106
242
|
const TOKEN_FILE_PATH = join(homedir(), ".ccjk", "cloud-token.json");
|
|
107
243
|
class CCJKCloudClient {
|
|
108
244
|
baseUrl;
|
|
109
245
|
deviceToken = null;
|
|
110
246
|
deviceId = null;
|
|
247
|
+
gateway = createDefaultGateway();
|
|
111
248
|
/**
|
|
112
249
|
* Create a new CCJKCloudClient instance
|
|
113
250
|
*
|
|
@@ -205,16 +342,35 @@ class CCJKCloudClient {
|
|
|
205
342
|
*/
|
|
206
343
|
async bind(code, deviceInfo) {
|
|
207
344
|
const info = deviceInfo ? { ...getDeviceInfo(), ...deviceInfo } : getDeviceInfo();
|
|
208
|
-
const
|
|
345
|
+
const requestPayload = {
|
|
346
|
+
code,
|
|
347
|
+
deviceInfo: info
|
|
348
|
+
};
|
|
349
|
+
const requestValidation = validateBindRequest(requestPayload);
|
|
350
|
+
if (!requestValidation.valid) {
|
|
351
|
+
return {
|
|
352
|
+
success: false,
|
|
353
|
+
error: `Invalid bind request: ${requestValidation.errors.join(", ")}`,
|
|
354
|
+
code: "VALIDATION_ERROR"
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
const response = await this.gateway.request("notifications.bind", {
|
|
209
358
|
method: "POST",
|
|
210
|
-
body:
|
|
211
|
-
|
|
212
|
-
deviceInfo: info
|
|
213
|
-
})
|
|
359
|
+
body: requestPayload,
|
|
360
|
+
authToken: this.deviceToken || void 0
|
|
214
361
|
});
|
|
362
|
+
const responseValidation = validateBindResponse(response);
|
|
363
|
+
if (!responseValidation.valid) {
|
|
364
|
+
return {
|
|
365
|
+
success: false,
|
|
366
|
+
error: `Invalid bind response: ${responseValidation.errors.join(", ")}`,
|
|
367
|
+
code: "RESPONSE_VALIDATION_ERROR"
|
|
368
|
+
};
|
|
369
|
+
}
|
|
215
370
|
if (response.success && response.data) {
|
|
216
371
|
this.deviceToken = response.data.deviceToken;
|
|
217
372
|
this.deviceId = response.data.deviceId;
|
|
373
|
+
this.gateway.setAuthToken(response.data.deviceToken);
|
|
218
374
|
this.saveToken({
|
|
219
375
|
deviceToken: response.data.deviceToken,
|
|
220
376
|
deviceId: response.data.deviceId,
|
|
@@ -224,8 +380,10 @@ class CCJKCloudClient {
|
|
|
224
380
|
});
|
|
225
381
|
return {
|
|
226
382
|
success: true,
|
|
227
|
-
|
|
228
|
-
|
|
383
|
+
data: {
|
|
384
|
+
deviceToken: response.data.deviceToken,
|
|
385
|
+
deviceId: response.data.deviceId
|
|
386
|
+
}
|
|
229
387
|
};
|
|
230
388
|
}
|
|
231
389
|
return {
|
|
@@ -261,21 +419,41 @@ class CCJKCloudClient {
|
|
|
261
419
|
code: "NOT_BOUND"
|
|
262
420
|
};
|
|
263
421
|
}
|
|
264
|
-
const
|
|
422
|
+
const requestPayload = {
|
|
423
|
+
title: options.title,
|
|
424
|
+
body: options.body,
|
|
425
|
+
type: options.type || "info",
|
|
426
|
+
taskId: options.taskId,
|
|
427
|
+
metadata: options.metadata,
|
|
428
|
+
actions: options.actions
|
|
429
|
+
};
|
|
430
|
+
const requestValidation = validateNotifyRequest(requestPayload);
|
|
431
|
+
if (!requestValidation.valid) {
|
|
432
|
+
return {
|
|
433
|
+
success: false,
|
|
434
|
+
error: `Invalid notify request: ${requestValidation.errors.join(", ")}`,
|
|
435
|
+
code: "VALIDATION_ERROR"
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
const response = await this.gateway.request("notifications.send", {
|
|
265
439
|
method: "POST",
|
|
266
|
-
body:
|
|
267
|
-
|
|
268
|
-
body: options.body,
|
|
269
|
-
type: options.type || "info",
|
|
270
|
-
taskId: options.taskId,
|
|
271
|
-
metadata: options.metadata,
|
|
272
|
-
actions: options.actions
|
|
273
|
-
})
|
|
440
|
+
body: requestPayload,
|
|
441
|
+
authToken: this.deviceToken
|
|
274
442
|
});
|
|
443
|
+
const responseValidation = validateNotifyResponse(response);
|
|
444
|
+
if (!responseValidation.valid) {
|
|
445
|
+
return {
|
|
446
|
+
success: false,
|
|
447
|
+
error: `Invalid notify response: ${responseValidation.errors.join(", ")}`,
|
|
448
|
+
code: "RESPONSE_VALIDATION_ERROR"
|
|
449
|
+
};
|
|
450
|
+
}
|
|
275
451
|
if (response.success && response.data) {
|
|
276
452
|
return {
|
|
277
453
|
success: true,
|
|
278
|
-
|
|
454
|
+
data: {
|
|
455
|
+
notificationId: response.data.notificationId
|
|
456
|
+
}
|
|
279
457
|
};
|
|
280
458
|
}
|
|
281
459
|
return {
|
|
@@ -309,11 +487,20 @@ class CCJKCloudClient {
|
|
|
309
487
|
if (!this.deviceToken) {
|
|
310
488
|
throw new Error('Device not bound. Please run "ccjk notification bind <code>" first.');
|
|
311
489
|
}
|
|
312
|
-
const response = await this.request(
|
|
490
|
+
const response = await this.gateway.request("notifications.poll", {
|
|
313
491
|
method: "GET",
|
|
492
|
+
query: { timeout },
|
|
493
|
+
authToken: this.deviceToken,
|
|
314
494
|
timeout
|
|
315
495
|
});
|
|
316
|
-
|
|
496
|
+
const responseValidation = validatePollResponse(response);
|
|
497
|
+
if (!responseValidation.valid) {
|
|
498
|
+
throw new Error(`Invalid poll response: ${responseValidation.errors.join(", ")}`);
|
|
499
|
+
}
|
|
500
|
+
if (!response.success) {
|
|
501
|
+
throw new Error(response.error || "Failed to poll for reply");
|
|
502
|
+
}
|
|
503
|
+
if (response.data?.reply) {
|
|
317
504
|
return {
|
|
318
505
|
content: response.data.reply.content,
|
|
319
506
|
timestamp: new Date(response.data.reply.timestamp),
|
|
@@ -397,72 +584,7 @@ class CCJKCloudClient {
|
|
|
397
584
|
deviceId: this.deviceId || void 0
|
|
398
585
|
};
|
|
399
586
|
}
|
|
400
|
-
//
|
|
401
|
-
// HTTP Request Helper
|
|
402
|
-
// ==========================================================================
|
|
403
|
-
/**
|
|
404
|
-
* Make an HTTP request to the cloud service
|
|
405
|
-
*/
|
|
406
|
-
async request(path, options) {
|
|
407
|
-
const url = `${this.baseUrl}${path}`;
|
|
408
|
-
const timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
409
|
-
const controller = new AbortController();
|
|
410
|
-
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
411
|
-
try {
|
|
412
|
-
const headers = {
|
|
413
|
-
"Content-Type": "application/json"
|
|
414
|
-
};
|
|
415
|
-
if (this.deviceToken) {
|
|
416
|
-
headers["X-Device-Token"] = this.deviceToken;
|
|
417
|
-
}
|
|
418
|
-
const response = await fetch(url, {
|
|
419
|
-
method: options.method,
|
|
420
|
-
headers,
|
|
421
|
-
body: options.body,
|
|
422
|
-
signal: controller.signal
|
|
423
|
-
});
|
|
424
|
-
clearTimeout(timeoutId);
|
|
425
|
-
const data = await response.json();
|
|
426
|
-
if (!response.ok) {
|
|
427
|
-
return {
|
|
428
|
-
success: false,
|
|
429
|
-
error: data.error || `HTTP ${response.status}: ${response.statusText}`,
|
|
430
|
-
code: data.code || `HTTP_${response.status}`
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
if (this.deviceToken && existsSync(TOKEN_FILE_PATH)) {
|
|
434
|
-
try {
|
|
435
|
-
const storageData = readFileSync(TOKEN_FILE_PATH, "utf-8");
|
|
436
|
-
const storage = JSON.parse(storageData);
|
|
437
|
-
storage.lastUsedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
438
|
-
writeFileAtomic(TOKEN_FILE_PATH, JSON.stringify(storage, null, 2));
|
|
439
|
-
} catch {
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
return data;
|
|
443
|
-
} catch (error) {
|
|
444
|
-
clearTimeout(timeoutId);
|
|
445
|
-
if (error instanceof Error) {
|
|
446
|
-
if (error.name === "AbortError") {
|
|
447
|
-
return {
|
|
448
|
-
success: false,
|
|
449
|
-
error: "Request timeout",
|
|
450
|
-
code: "TIMEOUT"
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
return {
|
|
454
|
-
success: false,
|
|
455
|
-
error: error.message,
|
|
456
|
-
code: "NETWORK_ERROR"
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
return {
|
|
460
|
-
success: false,
|
|
461
|
-
error: String(error),
|
|
462
|
-
code: "UNKNOWN_ERROR"
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
}
|
|
587
|
+
// Note: HTTP requests now handled by CloudApiGateway
|
|
466
588
|
}
|
|
467
589
|
let cloudClientInstance = null;
|
|
468
590
|
function getCloudNotificationClient() {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccjk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "12.0.
|
|
4
|
+
"version": "12.0.7",
|
|
5
5
|
"packageManager": "pnpm@10.17.1",
|
|
6
6
|
"description": "CLI toolkit for Claude Code and Codex setup. Simplifies MCP service installation, API configuration, workflow management, and multi-provider support with guided interactive setup.",
|
|
7
7
|
"author": {
|
|
@@ -106,6 +106,10 @@
|
|
|
106
106
|
"test:v2:coverage": "vitest run --config vitest.config.v2.ts --coverage",
|
|
107
107
|
"test:v2:run": "vitest run --config vitest.config.v2.ts",
|
|
108
108
|
"test:v2:watch": "vitest watch --config vitest.config.v2.ts",
|
|
109
|
+
"test:integration": "NODE_ENV=test vitest --config vitest.integration.config.ts",
|
|
110
|
+
"test:integration:run": "NODE_ENV=test vitest run --config vitest.integration.config.ts",
|
|
111
|
+
"test:integration:ui": "NODE_ENV=test vitest --config vitest.integration.config.ts --ui",
|
|
112
|
+
"test:integration:coverage": "NODE_ENV=test vitest run --config vitest.integration.config.ts --coverage",
|
|
109
113
|
"prepare": "husky",
|
|
110
114
|
"format": "prettier --write src/**/*.ts",
|
|
111
115
|
"prepublish:fix": "node scripts/fix-package-catalog.mjs",
|