ccjk 13.4.0 → 13.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/ccjk-all.mjs +1 -1
- package/dist/chunks/codex.mjs +12 -6
- package/dist/chunks/menu.mjs +14 -2
- package/dist/chunks/package.mjs +1 -1
- package/dist/cli.mjs +0 -0
- package/dist/i18n/locales/en/codex.json +17 -0
- package/dist/i18n/locales/en/menu.json +28 -1
- package/dist/i18n/locales/zh-CN/codex.json +17 -0
- package/dist/i18n/locales/zh-CN/menu.json +28 -1
- package/dist/index.d.mts +67 -1
- package/dist/index.d.ts +67 -1
- package/dist/index.mjs +8 -11
- package/dist/shared/{ccjk.BNVSnyu0.mjs → ccjk.C3YuTovw.mjs} +174 -14
- package/package.json +65 -68
package/dist/chunks/ccjk-all.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import a from './index2.mjs';
|
|
2
2
|
import { c as consola, a as analyzeProject } from '../shared/ccjk.DypYla6I.mjs';
|
|
3
|
-
import { c as createCompleteCloudClient } from '../shared/ccjk.
|
|
3
|
+
import { c as createCompleteCloudClient } from '../shared/ccjk.C3YuTovw.mjs';
|
|
4
4
|
import { i18n, ensureI18nInitialized } from './index5.mjs';
|
|
5
5
|
import { createHash } from 'node:crypto';
|
|
6
6
|
import { promises, readFileSync } from 'node:fs';
|
package/dist/chunks/codex.mjs
CHANGED
|
@@ -7,11 +7,11 @@ import ora from './index7.mjs';
|
|
|
7
7
|
import { a as semver } from '../shared/ccjk.CxpGa6MC.mjs';
|
|
8
8
|
import { p as parse } from '../shared/ccjk.BBtCGd_g.mjs';
|
|
9
9
|
import { x as K } from './main.mjs';
|
|
10
|
-
import { CODEX_AUTH_FILE, SUPPORTED_LANGS, CODEX_DIR, CODEX_AGENTS_FILE, CODEX_PROMPTS_DIR,
|
|
10
|
+
import { CODEX_AUTH_FILE, SUPPORTED_LANGS, CODEX_CONFIG_FILE, CODEX_DIR, CODEX_AGENTS_FILE, CODEX_PROMPTS_DIR, AI_OUTPUT_LANGUAGES, ZCF_CONFIG_FILE } from './constants.mjs';
|
|
11
11
|
import { ensureI18nInitialized, i18n, format } from './index5.mjs';
|
|
12
12
|
import { updateZcfConfig, readZcfConfig, readDefaultTomlConfig, updateTomlConfig } from './ccjk-config.mjs';
|
|
13
13
|
import { e as applyAiLanguageDirective } from './config2.mjs';
|
|
14
|
-
import { exists, readFile, ensureDir, writeFileAtomic, writeFile,
|
|
14
|
+
import { exists, readFile, ensureDir, writeFileAtomic, writeFile, copyDir, copyFile } from './fs-operations.mjs';
|
|
15
15
|
import { readJsonConfig, writeJsonConfig } from './json-config.mjs';
|
|
16
16
|
import { i as isWindows, m as getMcpCommand, l as getSystemRoot, w as wrapCommandWithSudo, n as normalizeTomlPath } from './platform.mjs';
|
|
17
17
|
import { a as addNumbersToChoices } from '../shared/ccjk.BFQ7yr5S.mjs';
|
|
@@ -809,10 +809,13 @@ function writeCodexConfig(data) {
|
|
|
809
809
|
ensureDir(CODEX_DIR);
|
|
810
810
|
writeFileAtomic(CODEX_CONFIG_FILE, renderCodexConfig(data));
|
|
811
811
|
}
|
|
812
|
-
function writeAuthFile(newEntries) {
|
|
812
|
+
function writeAuthFile(newEntries, authMode) {
|
|
813
813
|
ensureDir(CODEX_DIR);
|
|
814
814
|
const existing = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
|
|
815
815
|
const merged = { ...existing, ...newEntries };
|
|
816
|
+
if (authMode) {
|
|
817
|
+
merged.auth_mode = authMode;
|
|
818
|
+
}
|
|
816
819
|
writeJsonConfig(CODEX_AUTH_FILE, merged, { pretty: true });
|
|
817
820
|
}
|
|
818
821
|
async function isCodexInstalled() {
|
|
@@ -1177,7 +1180,7 @@ async function applyCustomApiConfig(customApiConfig) {
|
|
|
1177
1180
|
otherConfig: existingConfig?.otherConfig || []
|
|
1178
1181
|
};
|
|
1179
1182
|
writeCodexConfig(configData);
|
|
1180
|
-
writeJsonConfig(CODEX_AUTH_FILE, authEntries);
|
|
1183
|
+
writeJsonConfig(CODEX_AUTH_FILE, { ...authEntries, auth_mode: "apikey" });
|
|
1181
1184
|
updateZcfConfig({ codeToolType: "codex" });
|
|
1182
1185
|
console.log(a.green(`\u2714 ${i18n.t("codex:apiConfigured")}`));
|
|
1183
1186
|
}
|
|
@@ -1385,7 +1388,8 @@ async function configureCodexApi(options) {
|
|
|
1385
1388
|
baseUrl: selectedProvider2 === "custom" ? answers.baseUrl : prefilledBaseUrl,
|
|
1386
1389
|
wireApi: selectedProvider2 === "custom" ? answers.wireApi || "responses" : prefilledWireApi,
|
|
1387
1390
|
tempEnvKey,
|
|
1388
|
-
requiresOpenaiAuth:
|
|
1391
|
+
requiresOpenaiAuth: false,
|
|
1392
|
+
// Custom/third-party providers use their own API key, not OpenAI OAuth
|
|
1389
1393
|
model: customModel || prefilledModel || "gpt-5-codex"
|
|
1390
1394
|
// Use custom model, provider's default model, or fallback
|
|
1391
1395
|
};
|
|
@@ -1423,7 +1427,7 @@ async function configureCodexApi(options) {
|
|
|
1423
1427
|
mcpServices: existingConfig?.mcpServices || [],
|
|
1424
1428
|
otherConfig: existingConfig?.otherConfig || []
|
|
1425
1429
|
});
|
|
1426
|
-
writeAuthFile(authEntries);
|
|
1430
|
+
writeAuthFile(authEntries, "apikey");
|
|
1427
1431
|
updateZcfConfig({ codeToolType: "codex" });
|
|
1428
1432
|
console.log(a.green(i18n.t("codex:apiConfigured")));
|
|
1429
1433
|
}
|
|
@@ -1654,6 +1658,7 @@ async function switchToOfficialLogin() {
|
|
|
1654
1658
|
writeCodexConfig(updatedConfig);
|
|
1655
1659
|
const auth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
|
|
1656
1660
|
auth.OPENAI_API_KEY = null;
|
|
1661
|
+
auth.auth_mode = "chatgpt";
|
|
1657
1662
|
writeJsonConfig(CODEX_AUTH_FILE, auth, { pretty: true });
|
|
1658
1663
|
console.log(a.green(i18n.t("codex:officialConfigured")));
|
|
1659
1664
|
return true;
|
|
@@ -1699,6 +1704,7 @@ async function switchToProvider(providerId) {
|
|
|
1699
1704
|
const auth = readJsonConfig(CODEX_AUTH_FILE, { defaultValue: {} }) || {};
|
|
1700
1705
|
const envValue = auth[provider.tempEnvKey] || null;
|
|
1701
1706
|
auth.OPENAI_API_KEY = envValue;
|
|
1707
|
+
auth.auth_mode = "apikey";
|
|
1702
1708
|
writeJsonConfig(CODEX_AUTH_FILE, auth, { pretty: true });
|
|
1703
1709
|
console.log(a.green(i18n.t("codex:providerSwitchSuccess", { provider: providerId })));
|
|
1704
1710
|
return true;
|
package/dist/chunks/menu.mjs
CHANGED
|
@@ -417,7 +417,13 @@ async function handleHierarchicalMenu() {
|
|
|
417
417
|
break;
|
|
418
418
|
}
|
|
419
419
|
case "5": {
|
|
420
|
-
|
|
420
|
+
const currentCodeTool = getCurrentCodeTool();
|
|
421
|
+
if (currentCodeTool === "codex") {
|
|
422
|
+
const { configureCodexApi } = await import('./codex.mjs').then(function (n) { return n.i; });
|
|
423
|
+
await configureCodexApi();
|
|
424
|
+
} else {
|
|
425
|
+
await configureApiFeature();
|
|
426
|
+
}
|
|
421
427
|
break;
|
|
422
428
|
}
|
|
423
429
|
case "6": {
|
|
@@ -515,7 +521,13 @@ async function showSimplifiedMenu() {
|
|
|
515
521
|
break;
|
|
516
522
|
}
|
|
517
523
|
case "3": {
|
|
518
|
-
|
|
524
|
+
const currentCodeTool = getCurrentCodeTool();
|
|
525
|
+
if (currentCodeTool === "codex") {
|
|
526
|
+
const { configureCodexApi } = await import('./codex.mjs').then(function (n) { return n.i; });
|
|
527
|
+
await configureCodexApi();
|
|
528
|
+
} else {
|
|
529
|
+
await configureApiFeature();
|
|
530
|
+
}
|
|
519
531
|
break;
|
|
520
532
|
}
|
|
521
533
|
case "4": {
|
package/dist/chunks/package.mjs
CHANGED
package/dist/cli.mjs
CHANGED
|
File without changes
|
|
@@ -121,6 +121,23 @@
|
|
|
121
121
|
"providerManager.wireApiInvalid": "Wire API must be either \"responses\" or \"chat\"",
|
|
122
122
|
"providerManager.unknownError": "Unknown error",
|
|
123
123
|
"envKeyMigrationComplete": "✔ env_key to temp_env_key migration completed",
|
|
124
|
+
"presetPrompt": "Select a Codex preset bundle",
|
|
125
|
+
"presetApplied": "✔ Codex preset applied: {{preset}}",
|
|
126
|
+
"presetSummary": "Workflows {{workflows}} · MCP {{services}}",
|
|
127
|
+
"presets": {
|
|
128
|
+
"minimal": {
|
|
129
|
+
"name": "Minimal",
|
|
130
|
+
"description": "Lean workflow bundle with search and docs MCP"
|
|
131
|
+
},
|
|
132
|
+
"dev": {
|
|
133
|
+
"name": "Dev",
|
|
134
|
+
"description": "Balanced workflow bundle with search, docs, and repo context"
|
|
135
|
+
},
|
|
136
|
+
"full": {
|
|
137
|
+
"name": "Full",
|
|
138
|
+
"description": "Expanded workflow bundle with deeper repo assistance"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
124
141
|
"errorSwitchingProvider": "Error switching provider: {{error}}",
|
|
125
142
|
"errorSwitchingToOfficialLogin": "Error switching to official login: {{error}}",
|
|
126
143
|
"errorDuringUninstall": "Error during uninstall: {{error}}"
|
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
"changeLanguage": "Change Language / 切换语言",
|
|
44
44
|
"switchCodeTool": "Switch Code Tool",
|
|
45
45
|
"uninstall": "Uninstall CCJK",
|
|
46
|
+
"codexImportWorkflow": "Import Workflows",
|
|
47
|
+
"codexPreset": "Preset Bundle",
|
|
46
48
|
"mcpMarket": "MCP Market",
|
|
47
49
|
"marketplace": "Marketplace",
|
|
48
50
|
"hooksSync": "Hooks Sync",
|
|
@@ -56,6 +58,8 @@
|
|
|
56
58
|
"changeLanguage": "Switch interface language",
|
|
57
59
|
"switchCodeTool": "Switch between different code tools",
|
|
58
60
|
"uninstall": "Uninstall CCJK and related configurations",
|
|
61
|
+
"codexImportWorkflow": "Install Codex prompt workflows and AGENTS templates",
|
|
62
|
+
"codexPreset": "Apply a ready-made Codex capability bundle for workflows and MCP services",
|
|
59
63
|
"mcpMarket": "Browse and install MCP services",
|
|
60
64
|
"marketplace": "Browse and install extension packages",
|
|
61
65
|
"hooksSync": "Sync Git Hooks configuration",
|
|
@@ -65,6 +69,29 @@
|
|
|
65
69
|
"outputStyles": "Configure output styles",
|
|
66
70
|
"doctor": "Run environment health check"
|
|
67
71
|
},
|
|
72
|
+
"toolMode": {
|
|
73
|
+
"claude": {
|
|
74
|
+
"title": "Claude Workspace",
|
|
75
|
+
"summary": "Full CCJK surface with diagnostics, cloud sync, and extensions.",
|
|
76
|
+
"focus": "Workflows, diagnostics, permissions, and cloud-connected tools.",
|
|
77
|
+
"config": "Primary config: ~/.claude/settings.json",
|
|
78
|
+
"menuTitle": "Claude Control Center"
|
|
79
|
+
},
|
|
80
|
+
"codex": {
|
|
81
|
+
"title": "Codex Workspace",
|
|
82
|
+
"summary": "Lean setup focused on provider wiring, prompts, MCP, and memory.",
|
|
83
|
+
"focus": "API provider, MCP services, default model, and AGENTS-based memory.",
|
|
84
|
+
"config": "Primary config: ~/.codex/config.toml",
|
|
85
|
+
"menuTitle": "Codex Control Center"
|
|
86
|
+
},
|
|
87
|
+
"generic": {
|
|
88
|
+
"title": "Tool Workspace",
|
|
89
|
+
"summary": "CCJK adapts the menu to the active coding tool.",
|
|
90
|
+
"focus": "Core setup, configuration, and tool-specific actions.",
|
|
91
|
+
"config": "Using the active tool configuration profile.",
|
|
92
|
+
"menuTitle": "CCJK Control Center"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
68
95
|
"menu": {
|
|
69
96
|
"title": "CCJK Main Menu",
|
|
70
97
|
"breadcrumb": {
|
|
@@ -194,4 +221,4 @@
|
|
|
194
221
|
"exit": "0. 🚪 Exit"
|
|
195
222
|
},
|
|
196
223
|
"memoryManagement": "M. Memory Management"
|
|
197
|
-
}
|
|
224
|
+
}
|
|
@@ -121,6 +121,23 @@
|
|
|
121
121
|
"providerManager.wireApiInvalid": "Wire API 必须是 \"responses\" 或 \"chat\"",
|
|
122
122
|
"providerManager.unknownError": "未知错误",
|
|
123
123
|
"envKeyMigrationComplete": "✔ 已完成 env_key 到 temp_env_key 的迁移",
|
|
124
|
+
"presetPrompt": "选择一个 Codex 预设套装",
|
|
125
|
+
"presetApplied": "✔ 已应用 Codex 预设:{{preset}}",
|
|
126
|
+
"presetSummary": "工作流 {{workflows}} · MCP {{services}}",
|
|
127
|
+
"presets": {
|
|
128
|
+
"minimal": {
|
|
129
|
+
"name": "Minimal",
|
|
130
|
+
"description": "轻量工作流套装,包含搜索与文档 MCP"
|
|
131
|
+
},
|
|
132
|
+
"dev": {
|
|
133
|
+
"name": "Dev",
|
|
134
|
+
"description": "均衡开发工作流套装,包含搜索、文档与仓库上下文能力"
|
|
135
|
+
},
|
|
136
|
+
"full": {
|
|
137
|
+
"name": "Full",
|
|
138
|
+
"description": "增强型工作流套装,提供更完整的仓库辅助能力"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
124
141
|
"errorSwitchingProvider": "切换提供商时出错:{{error}}",
|
|
125
142
|
"errorSwitchingToOfficialLogin": "切换到官方登录时出错:{{error}}",
|
|
126
143
|
"errorDuringUninstall": "卸载过程中出错:{{error}}"
|
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
"changeLanguage": "切换语言 / Change Language",
|
|
44
44
|
"switchCodeTool": "切换代码工具",
|
|
45
45
|
"uninstall": "卸载 CCJK",
|
|
46
|
+
"codexImportWorkflow": "导入工作流",
|
|
47
|
+
"codexPreset": "预设套装",
|
|
46
48
|
"mcpMarket": "MCP 市场",
|
|
47
49
|
"marketplace": "扩展市场",
|
|
48
50
|
"hooksSync": "Hooks 同步",
|
|
@@ -56,6 +58,8 @@
|
|
|
56
58
|
"changeLanguage": "切换界面语言",
|
|
57
59
|
"switchCodeTool": "在不同代码工具之间切换",
|
|
58
60
|
"uninstall": "卸载 CCJK 及相关配置",
|
|
61
|
+
"codexImportWorkflow": "安装 Codex Prompt 工作流与 AGENTS 模板",
|
|
62
|
+
"codexPreset": "一键套用 Codex 能力套装,仅增强工作流与 MCP 服务",
|
|
59
63
|
"mcpMarket": "浏览和安装 MCP 服务",
|
|
60
64
|
"marketplace": "浏览和安装扩展包",
|
|
61
65
|
"hooksSync": "同步 Git Hooks 配置",
|
|
@@ -65,6 +69,29 @@
|
|
|
65
69
|
"outputStyles": "配置输出样式",
|
|
66
70
|
"doctor": "运行环境健康检查"
|
|
67
71
|
},
|
|
72
|
+
"toolMode": {
|
|
73
|
+
"claude": {
|
|
74
|
+
"title": "Claude 工作台",
|
|
75
|
+
"summary": "完整 CCJK 界面,包含诊断、云功能与扩展能力。",
|
|
76
|
+
"focus": "工作流、诊断、权限配置与云端集成功能。",
|
|
77
|
+
"config": "主配置文件:~/.claude/settings.json",
|
|
78
|
+
"menuTitle": "Claude 控制中心"
|
|
79
|
+
},
|
|
80
|
+
"codex": {
|
|
81
|
+
"title": "Codex 工作台",
|
|
82
|
+
"summary": "精简界面,聚焦 Provider 接线、Prompts、MCP 与记忆配置。",
|
|
83
|
+
"focus": "API Provider、MCP 服务、默认模型与 AGENTS 记忆。",
|
|
84
|
+
"config": "主配置文件:~/.codex/config.toml",
|
|
85
|
+
"menuTitle": "Codex 控制中心"
|
|
86
|
+
},
|
|
87
|
+
"generic": {
|
|
88
|
+
"title": "工具工作台",
|
|
89
|
+
"summary": "CCJK 会根据当前代码工具自动调整菜单界面。",
|
|
90
|
+
"focus": "核心初始化、配置管理与工具专属操作。",
|
|
91
|
+
"config": "使用当前激活工具的配置档案。",
|
|
92
|
+
"menuTitle": "CCJK 控制中心"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
68
95
|
"menu": {
|
|
69
96
|
"title": "CCJK 主菜单",
|
|
70
97
|
"breadcrumb": {
|
|
@@ -194,4 +221,4 @@
|
|
|
194
221
|
"exit": "0. 🚪 退出"
|
|
195
222
|
},
|
|
196
223
|
"memoryManagement": "M. Memory 管理"
|
|
197
|
-
}
|
|
224
|
+
}
|
package/dist/index.d.mts
CHANGED
|
@@ -579,7 +579,7 @@ interface BatchTemplateResponse$1 {
|
|
|
579
579
|
/**
|
|
580
580
|
* Usage metric type
|
|
581
581
|
*/
|
|
582
|
-
type MetricType = 'template_download' | 'recommendation_shown' | 'recommendation_accepted' | 'analysis_completed' | 'error_occurred';
|
|
582
|
+
type MetricType = 'template_download' | 'recommendation_shown' | 'recommendation_accepted' | 'analysis_completed' | 'error_occurred' | 'command_run' | (string & {});
|
|
583
583
|
/**
|
|
584
584
|
* Usage report payload
|
|
585
585
|
*/
|
|
@@ -596,6 +596,10 @@ interface UsageReport {
|
|
|
596
596
|
nodeVersion: string;
|
|
597
597
|
/** Operating system */
|
|
598
598
|
platform: string;
|
|
599
|
+
/** Stable device identifier */
|
|
600
|
+
deviceId?: string;
|
|
601
|
+
/** Client version reported to analytics endpoints */
|
|
602
|
+
clientVersion?: string;
|
|
599
603
|
/** Project language if applicable */
|
|
600
604
|
language?: string;
|
|
601
605
|
/** Additional context data - use TelemetryEventData from dto.ts for strict typing */
|
|
@@ -679,10 +683,22 @@ interface CloudClientConfig {
|
|
|
679
683
|
maxRetries?: number;
|
|
680
684
|
/** Enable telemetry reporting */
|
|
681
685
|
enableTelemetry?: boolean;
|
|
686
|
+
/** Enable client usage analytics endpoints */
|
|
687
|
+
enableUsageAnalytics?: boolean;
|
|
682
688
|
/** API key if required */
|
|
683
689
|
apiKey?: string;
|
|
684
690
|
/** Language for API responses */
|
|
685
691
|
language?: string;
|
|
692
|
+
/** Stable device token for analytics/auth headers */
|
|
693
|
+
deviceToken?: string;
|
|
694
|
+
/** Stable device ID for usage analytics dedupe */
|
|
695
|
+
deviceId?: string;
|
|
696
|
+
/** Stable anonymous installation/user ID */
|
|
697
|
+
anonymousUserId?: string;
|
|
698
|
+
/** Override analytics platform label */
|
|
699
|
+
platform?: string;
|
|
700
|
+
/** Automatically send startup handshake on initialization */
|
|
701
|
+
autoHandshake?: boolean;
|
|
686
702
|
}
|
|
687
703
|
/**
|
|
688
704
|
* Cache entry metadata
|
|
@@ -723,6 +739,43 @@ interface TelemetryConfig {
|
|
|
723
739
|
/** Anonymous user ID */
|
|
724
740
|
userId?: string;
|
|
725
741
|
}
|
|
742
|
+
interface ClientIdentity {
|
|
743
|
+
deviceId: string;
|
|
744
|
+
anonymousUserId: string;
|
|
745
|
+
clientVersion: string;
|
|
746
|
+
platform: string;
|
|
747
|
+
deviceToken?: string;
|
|
748
|
+
}
|
|
749
|
+
interface DeviceRegistrationRequest {
|
|
750
|
+
deviceId: string;
|
|
751
|
+
platform: string;
|
|
752
|
+
clientVersion: string;
|
|
753
|
+
}
|
|
754
|
+
interface DeviceRegistrationResponse {
|
|
755
|
+
success: boolean;
|
|
756
|
+
requestId?: string;
|
|
757
|
+
message?: string;
|
|
758
|
+
}
|
|
759
|
+
interface HandshakeRequest {
|
|
760
|
+
deviceId: string;
|
|
761
|
+
platform: string;
|
|
762
|
+
clientVersion: string;
|
|
763
|
+
}
|
|
764
|
+
interface HandshakeResponse {
|
|
765
|
+
success: boolean;
|
|
766
|
+
requestId?: string;
|
|
767
|
+
message?: string;
|
|
768
|
+
}
|
|
769
|
+
interface SyncRequest {
|
|
770
|
+
deviceId: string;
|
|
771
|
+
platform: string;
|
|
772
|
+
clientVersion: string;
|
|
773
|
+
}
|
|
774
|
+
interface SyncResponse {
|
|
775
|
+
success: boolean;
|
|
776
|
+
requestId?: string;
|
|
777
|
+
message?: string;
|
|
778
|
+
}
|
|
726
779
|
|
|
727
780
|
/**
|
|
728
781
|
* Cloud Client Implementation
|
|
@@ -739,7 +792,14 @@ interface TelemetryConfig {
|
|
|
739
792
|
declare class CloudClient {
|
|
740
793
|
private fetch;
|
|
741
794
|
private config;
|
|
795
|
+
private identity;
|
|
742
796
|
constructor(config: CloudClientConfig);
|
|
797
|
+
private getDefaultHeaders;
|
|
798
|
+
private resolveIdentity;
|
|
799
|
+
private loadOrCreateStoredIdentity;
|
|
800
|
+
private buildAnalyticsPayload;
|
|
801
|
+
private canSendUsageAnalytics;
|
|
802
|
+
getIdentity(): ClientIdentity;
|
|
743
803
|
/**
|
|
744
804
|
* Calculate retry delay with exponential backoff
|
|
745
805
|
*/
|
|
@@ -812,6 +872,9 @@ declare class CloudClient {
|
|
|
812
872
|
* Get current configuration
|
|
813
873
|
*/
|
|
814
874
|
getConfig(): CloudClientConfig;
|
|
875
|
+
registerDevice(payload?: Partial<DeviceRegistrationRequest>): Promise<DeviceRegistrationResponse>;
|
|
876
|
+
handshake(payload?: Partial<HandshakeRequest>): Promise<HandshakeResponse>;
|
|
877
|
+
syncClientUsage(payload?: Partial<SyncRequest>): Promise<SyncResponse>;
|
|
815
878
|
}
|
|
816
879
|
/**
|
|
817
880
|
* Create a default cloud client instance
|
|
@@ -2595,6 +2658,9 @@ declare class FallbackCloudClient {
|
|
|
2595
2658
|
* Report usage (no fallback)
|
|
2596
2659
|
*/
|
|
2597
2660
|
reportUsage(report: UsageReport): Promise<UsageReportResponse>;
|
|
2661
|
+
registerDevice(payload?: Partial<DeviceRegistrationRequest>): Promise<DeviceRegistrationResponse>;
|
|
2662
|
+
handshake(payload?: Partial<HandshakeRequest>): Promise<HandshakeResponse>;
|
|
2663
|
+
syncClientUsage(payload?: Partial<SyncRequest>): Promise<SyncResponse>;
|
|
2598
2664
|
/**
|
|
2599
2665
|
* Health check (no fallback)
|
|
2600
2666
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -579,7 +579,7 @@ interface BatchTemplateResponse$1 {
|
|
|
579
579
|
/**
|
|
580
580
|
* Usage metric type
|
|
581
581
|
*/
|
|
582
|
-
type MetricType = 'template_download' | 'recommendation_shown' | 'recommendation_accepted' | 'analysis_completed' | 'error_occurred';
|
|
582
|
+
type MetricType = 'template_download' | 'recommendation_shown' | 'recommendation_accepted' | 'analysis_completed' | 'error_occurred' | 'command_run' | (string & {});
|
|
583
583
|
/**
|
|
584
584
|
* Usage report payload
|
|
585
585
|
*/
|
|
@@ -596,6 +596,10 @@ interface UsageReport {
|
|
|
596
596
|
nodeVersion: string;
|
|
597
597
|
/** Operating system */
|
|
598
598
|
platform: string;
|
|
599
|
+
/** Stable device identifier */
|
|
600
|
+
deviceId?: string;
|
|
601
|
+
/** Client version reported to analytics endpoints */
|
|
602
|
+
clientVersion?: string;
|
|
599
603
|
/** Project language if applicable */
|
|
600
604
|
language?: string;
|
|
601
605
|
/** Additional context data - use TelemetryEventData from dto.ts for strict typing */
|
|
@@ -679,10 +683,22 @@ interface CloudClientConfig {
|
|
|
679
683
|
maxRetries?: number;
|
|
680
684
|
/** Enable telemetry reporting */
|
|
681
685
|
enableTelemetry?: boolean;
|
|
686
|
+
/** Enable client usage analytics endpoints */
|
|
687
|
+
enableUsageAnalytics?: boolean;
|
|
682
688
|
/** API key if required */
|
|
683
689
|
apiKey?: string;
|
|
684
690
|
/** Language for API responses */
|
|
685
691
|
language?: string;
|
|
692
|
+
/** Stable device token for analytics/auth headers */
|
|
693
|
+
deviceToken?: string;
|
|
694
|
+
/** Stable device ID for usage analytics dedupe */
|
|
695
|
+
deviceId?: string;
|
|
696
|
+
/** Stable anonymous installation/user ID */
|
|
697
|
+
anonymousUserId?: string;
|
|
698
|
+
/** Override analytics platform label */
|
|
699
|
+
platform?: string;
|
|
700
|
+
/** Automatically send startup handshake on initialization */
|
|
701
|
+
autoHandshake?: boolean;
|
|
686
702
|
}
|
|
687
703
|
/**
|
|
688
704
|
* Cache entry metadata
|
|
@@ -723,6 +739,43 @@ interface TelemetryConfig {
|
|
|
723
739
|
/** Anonymous user ID */
|
|
724
740
|
userId?: string;
|
|
725
741
|
}
|
|
742
|
+
interface ClientIdentity {
|
|
743
|
+
deviceId: string;
|
|
744
|
+
anonymousUserId: string;
|
|
745
|
+
clientVersion: string;
|
|
746
|
+
platform: string;
|
|
747
|
+
deviceToken?: string;
|
|
748
|
+
}
|
|
749
|
+
interface DeviceRegistrationRequest {
|
|
750
|
+
deviceId: string;
|
|
751
|
+
platform: string;
|
|
752
|
+
clientVersion: string;
|
|
753
|
+
}
|
|
754
|
+
interface DeviceRegistrationResponse {
|
|
755
|
+
success: boolean;
|
|
756
|
+
requestId?: string;
|
|
757
|
+
message?: string;
|
|
758
|
+
}
|
|
759
|
+
interface HandshakeRequest {
|
|
760
|
+
deviceId: string;
|
|
761
|
+
platform: string;
|
|
762
|
+
clientVersion: string;
|
|
763
|
+
}
|
|
764
|
+
interface HandshakeResponse {
|
|
765
|
+
success: boolean;
|
|
766
|
+
requestId?: string;
|
|
767
|
+
message?: string;
|
|
768
|
+
}
|
|
769
|
+
interface SyncRequest {
|
|
770
|
+
deviceId: string;
|
|
771
|
+
platform: string;
|
|
772
|
+
clientVersion: string;
|
|
773
|
+
}
|
|
774
|
+
interface SyncResponse {
|
|
775
|
+
success: boolean;
|
|
776
|
+
requestId?: string;
|
|
777
|
+
message?: string;
|
|
778
|
+
}
|
|
726
779
|
|
|
727
780
|
/**
|
|
728
781
|
* Cloud Client Implementation
|
|
@@ -739,7 +792,14 @@ interface TelemetryConfig {
|
|
|
739
792
|
declare class CloudClient {
|
|
740
793
|
private fetch;
|
|
741
794
|
private config;
|
|
795
|
+
private identity;
|
|
742
796
|
constructor(config: CloudClientConfig);
|
|
797
|
+
private getDefaultHeaders;
|
|
798
|
+
private resolveIdentity;
|
|
799
|
+
private loadOrCreateStoredIdentity;
|
|
800
|
+
private buildAnalyticsPayload;
|
|
801
|
+
private canSendUsageAnalytics;
|
|
802
|
+
getIdentity(): ClientIdentity;
|
|
743
803
|
/**
|
|
744
804
|
* Calculate retry delay with exponential backoff
|
|
745
805
|
*/
|
|
@@ -812,6 +872,9 @@ declare class CloudClient {
|
|
|
812
872
|
* Get current configuration
|
|
813
873
|
*/
|
|
814
874
|
getConfig(): CloudClientConfig;
|
|
875
|
+
registerDevice(payload?: Partial<DeviceRegistrationRequest>): Promise<DeviceRegistrationResponse>;
|
|
876
|
+
handshake(payload?: Partial<HandshakeRequest>): Promise<HandshakeResponse>;
|
|
877
|
+
syncClientUsage(payload?: Partial<SyncRequest>): Promise<SyncResponse>;
|
|
815
878
|
}
|
|
816
879
|
/**
|
|
817
880
|
* Create a default cloud client instance
|
|
@@ -2595,6 +2658,9 @@ declare class FallbackCloudClient {
|
|
|
2595
2658
|
* Report usage (no fallback)
|
|
2596
2659
|
*/
|
|
2597
2660
|
reportUsage(report: UsageReport): Promise<UsageReportResponse>;
|
|
2661
|
+
registerDevice(payload?: Partial<DeviceRegistrationRequest>): Promise<DeviceRegistrationResponse>;
|
|
2662
|
+
handshake(payload?: Partial<HandshakeRequest>): Promise<HandshakeResponse>;
|
|
2663
|
+
syncClientUsage(payload?: Partial<SyncRequest>): Promise<SyncResponse>;
|
|
2598
2664
|
/**
|
|
2599
2665
|
* Health check (no fallback)
|
|
2600
2666
|
*/
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { P as ProjectAnalyzer, T as TemplatesClient, d as analyzeDependencies, a as analyzeProject, h as batchAnalyze, b as createTemplatesClient, e as detectProject, f as detectProjectType, g as getTemplatesClient } from './shared/ccjk.DypYla6I.mjs';
|
|
2
|
-
import { a as createCloudClient } from './shared/ccjk.
|
|
3
|
-
export { C as CachedCloudClient, b as CloudCache, d as CloudClient, F as FallbackCloudClient, R as RetryableCloudClient, T as TelemetryReporter, c as createCompleteCloudClient, g as getTelemetry, i as initializeTelemetry, r as retryUtils, s as stopTelemetry, t as telemetryUtils, e as trackEvent, w as withRetry } from './shared/ccjk.
|
|
2
|
+
import { a as createCloudClient } from './shared/ccjk.C3YuTovw.mjs';
|
|
3
|
+
export { C as CachedCloudClient, b as CloudCache, d as CloudClient, F as FallbackCloudClient, R as RetryableCloudClient, T as TelemetryReporter, c as createCompleteCloudClient, g as getTelemetry, i as initializeTelemetry, r as retryUtils, s as stopTelemetry, t as telemetryUtils, e as trackEvent, w as withRetry } from './shared/ccjk.C3YuTovw.mjs';
|
|
4
4
|
import { CLOUD_ENDPOINTS } from './chunks/constants.mjs';
|
|
5
5
|
export { C as CloudError, a as CloudErrorCode, b as CloudErrorFactory, f as formatErrorForLogging, g as getRetryDelay, h as handleCloudError, i as isAuthError, c as isRateLimitError, d as isRetryableError, e as isRetryableErrorCode } from './shared/ccjk.D8ZLYSZZ.mjs';
|
|
6
6
|
import { e as extractString } from './shared/ccjk.C2jHOZVP.mjs';
|
|
@@ -270,15 +270,8 @@ function validateUsageReport(report) {
|
|
|
270
270
|
const errors = [];
|
|
271
271
|
if (!report.reportId || typeof report.reportId !== "string")
|
|
272
272
|
errors.push("reportId is required and must be a string");
|
|
273
|
-
|
|
274
|
-
"
|
|
275
|
-
"recommendation_shown",
|
|
276
|
-
"recommendation_accepted",
|
|
277
|
-
"analysis_completed",
|
|
278
|
-
"error_occurred"
|
|
279
|
-
];
|
|
280
|
-
if (!validMetricTypes.includes(report.metricType))
|
|
281
|
-
errors.push(`metricType must be one of: ${validMetricTypes.join(", ")}`);
|
|
273
|
+
if (!report.metricType || typeof report.metricType !== "string")
|
|
274
|
+
errors.push("metricType is required and must be a string");
|
|
282
275
|
if (!report.timestamp || typeof report.timestamp !== "string")
|
|
283
276
|
errors.push("timestamp is required and must be a string");
|
|
284
277
|
if (!report.ccjkVersion || typeof report.ccjkVersion !== "string")
|
|
@@ -287,6 +280,10 @@ function validateUsageReport(report) {
|
|
|
287
280
|
errors.push("nodeVersion is required and must be a string");
|
|
288
281
|
if (!report.platform || typeof report.platform !== "string")
|
|
289
282
|
errors.push("platform is required and must be a string");
|
|
283
|
+
if (report.deviceId !== void 0 && typeof report.deviceId !== "string")
|
|
284
|
+
errors.push("deviceId must be a string when provided");
|
|
285
|
+
if (report.clientVersion !== void 0 && typeof report.clientVersion !== "string")
|
|
286
|
+
errors.push("clientVersion must be a string when provided");
|
|
290
287
|
return {
|
|
291
288
|
valid: errors.length === 0,
|
|
292
289
|
errors
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { c as consola, o as ofetch } from './ccjk.DypYla6I.mjs';
|
|
2
|
-
import fs__default, { readFileSync } from 'node:fs';
|
|
3
|
-
import path__default, {
|
|
2
|
+
import fs__default, { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import path__default, { join, dirname } from 'node:path';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
4
5
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { CLOUD_ENDPOINTS } from '../chunks/constants.mjs';
|
|
6
6
|
import { randomUUID } from 'node:crypto';
|
|
7
|
+
import { CLOUD_ENDPOINTS } from '../chunks/constants.mjs';
|
|
7
8
|
|
|
8
9
|
const defaults = Object.freeze({
|
|
9
10
|
ignoreUnknown: false,
|
|
@@ -926,28 +927,96 @@ try {
|
|
|
926
927
|
}
|
|
927
928
|
const API_PREFIX = "/api/v1";
|
|
928
929
|
const HEALTH_PATH = `${API_PREFIX}/health`;
|
|
930
|
+
const CLIENT_USAGE_STATE_DIR = join(homedir(), ".ccjk");
|
|
931
|
+
const CLIENT_USAGE_STATE_FILE = join(CLIENT_USAGE_STATE_DIR, "cloud-client-identity.json");
|
|
929
932
|
class CloudClient {
|
|
930
933
|
fetch;
|
|
931
934
|
config;
|
|
935
|
+
identity;
|
|
932
936
|
constructor(config) {
|
|
933
937
|
this.config = {
|
|
934
938
|
timeout: 1e4,
|
|
935
939
|
enableRetry: true,
|
|
936
940
|
maxRetries: 3,
|
|
937
941
|
enableTelemetry: true,
|
|
942
|
+
enableUsageAnalytics: true,
|
|
943
|
+
autoHandshake: true,
|
|
938
944
|
...config
|
|
939
945
|
};
|
|
946
|
+
this.identity = this.resolveIdentity();
|
|
940
947
|
this.fetch = ofetch.create({
|
|
941
948
|
baseURL: this.config.baseURL,
|
|
942
949
|
timeout: this.config.timeout,
|
|
943
|
-
headers:
|
|
944
|
-
"User-Agent": `CCJK/${this.config.version || CCJK_VERSION}`,
|
|
945
|
-
...this.config.apiKey && { Authorization: `Bearer ${this.config.apiKey}` }
|
|
946
|
-
},
|
|
950
|
+
headers: this.getDefaultHeaders(),
|
|
947
951
|
retry: this.config.enableRetry ? this.config.maxRetries : 0,
|
|
948
952
|
retryDelay: (context) => this.calculateRetryDelay(context.options.retry || 0)
|
|
949
953
|
});
|
|
950
954
|
}
|
|
955
|
+
getDefaultHeaders() {
|
|
956
|
+
const headers = {
|
|
957
|
+
"User-Agent": `CCJK/${this.identity.clientVersion}`,
|
|
958
|
+
"X-CCJK-Version": this.identity.clientVersion,
|
|
959
|
+
"X-Anonymous-User-Id": this.identity.anonymousUserId
|
|
960
|
+
};
|
|
961
|
+
if (this.config.apiKey) {
|
|
962
|
+
headers.Authorization = `Bearer ${this.config.apiKey}`;
|
|
963
|
+
}
|
|
964
|
+
if (this.identity.deviceToken) {
|
|
965
|
+
headers["X-Device-Token"] = this.identity.deviceToken;
|
|
966
|
+
}
|
|
967
|
+
return headers;
|
|
968
|
+
}
|
|
969
|
+
resolveIdentity() {
|
|
970
|
+
const storedIdentity = this.loadOrCreateStoredIdentity();
|
|
971
|
+
const clientVersion = this.config.version || CCJK_VERSION;
|
|
972
|
+
return {
|
|
973
|
+
anonymousUserId: this.config.anonymousUserId || storedIdentity.anonymousUserId,
|
|
974
|
+
deviceId: this.config.deviceId || storedIdentity.deviceId,
|
|
975
|
+
clientVersion,
|
|
976
|
+
platform: this.config.platform || process.platform,
|
|
977
|
+
deviceToken: this.config.deviceToken
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
loadOrCreateStoredIdentity() {
|
|
981
|
+
try {
|
|
982
|
+
if (existsSync(CLIENT_USAGE_STATE_FILE)) {
|
|
983
|
+
const stored = JSON.parse(readFileSync(CLIENT_USAGE_STATE_FILE, "utf-8"));
|
|
984
|
+
if (stored.anonymousUserId && stored.deviceId) {
|
|
985
|
+
return {
|
|
986
|
+
anonymousUserId: stored.anonymousUserId,
|
|
987
|
+
deviceId: stored.deviceId
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
} catch (error) {
|
|
992
|
+
consola.debug("Failed to read stored cloud client identity:", error);
|
|
993
|
+
}
|
|
994
|
+
const generated = {
|
|
995
|
+
anonymousUserId: process.env.CCJK_ANONYMOUS_USER_ID || randomUUID(),
|
|
996
|
+
deviceId: process.env.CCJK_DEVICE_ID || randomUUID()
|
|
997
|
+
};
|
|
998
|
+
try {
|
|
999
|
+
mkdirSync(CLIENT_USAGE_STATE_DIR, { recursive: true });
|
|
1000
|
+
writeFileSync(CLIENT_USAGE_STATE_FILE, JSON.stringify(generated, null, 2));
|
|
1001
|
+
} catch (error) {
|
|
1002
|
+
consola.debug("Failed to persist cloud client identity:", error);
|
|
1003
|
+
}
|
|
1004
|
+
return generated;
|
|
1005
|
+
}
|
|
1006
|
+
buildAnalyticsPayload(payload) {
|
|
1007
|
+
return {
|
|
1008
|
+
deviceId: payload?.deviceId || this.identity.deviceId,
|
|
1009
|
+
platform: payload?.platform || this.identity.platform,
|
|
1010
|
+
clientVersion: payload?.clientVersion || this.identity.clientVersion,
|
|
1011
|
+
...payload
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
canSendUsageAnalytics() {
|
|
1015
|
+
return this.config.enableUsageAnalytics !== false;
|
|
1016
|
+
}
|
|
1017
|
+
getIdentity() {
|
|
1018
|
+
return { ...this.identity };
|
|
1019
|
+
}
|
|
951
1020
|
/**
|
|
952
1021
|
* Calculate retry delay with exponential backoff
|
|
953
1022
|
*/
|
|
@@ -1102,11 +1171,24 @@ class CloudClient {
|
|
|
1102
1171
|
* @returns Usage report response
|
|
1103
1172
|
*/
|
|
1104
1173
|
async reportUsage(report) {
|
|
1174
|
+
if (!this.canSendUsageAnalytics()) {
|
|
1175
|
+
return {
|
|
1176
|
+
success: false,
|
|
1177
|
+
requestId: "",
|
|
1178
|
+
message: "Usage analytics disabled"
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1105
1181
|
try {
|
|
1106
1182
|
consola.debug("Reporting usage:", report.metricType);
|
|
1183
|
+
const payload = {
|
|
1184
|
+
...report,
|
|
1185
|
+
deviceId: report.deviceId || this.identity.deviceId,
|
|
1186
|
+
platform: report.platform || this.identity.platform,
|
|
1187
|
+
clientVersion: report.clientVersion || report.ccjkVersion || this.identity.clientVersion
|
|
1188
|
+
};
|
|
1107
1189
|
const response = await this.fetch(`${API_PREFIX}/usage/current`, {
|
|
1108
1190
|
method: "POST",
|
|
1109
|
-
body:
|
|
1191
|
+
body: payload,
|
|
1110
1192
|
timeout: 5e3
|
|
1111
1193
|
// 5s timeout - telemetry should be fast
|
|
1112
1194
|
});
|
|
@@ -1147,14 +1229,12 @@ class CloudClient {
|
|
|
1147
1229
|
*/
|
|
1148
1230
|
updateConfig(config) {
|
|
1149
1231
|
this.config = { ...this.config, ...config };
|
|
1150
|
-
|
|
1232
|
+
this.identity = this.resolveIdentity();
|
|
1233
|
+
if (config.baseURL || config.timeout || config.apiKey || config.version || config.deviceToken || config.anonymousUserId || config.deviceId || config.platform) {
|
|
1151
1234
|
this.fetch = ofetch.create({
|
|
1152
1235
|
baseURL: this.config.baseURL,
|
|
1153
1236
|
timeout: this.config.timeout,
|
|
1154
|
-
headers:
|
|
1155
|
-
"User-Agent": `CCJK/${this.config.version || CCJK_VERSION}`,
|
|
1156
|
-
...this.config.apiKey && { Authorization: `Bearer ${this.config.apiKey}` }
|
|
1157
|
-
},
|
|
1237
|
+
headers: this.getDefaultHeaders(),
|
|
1158
1238
|
retry: this.config.enableRetry ? this.config.maxRetries : 0,
|
|
1159
1239
|
retryDelay: (context) => this.calculateRetryDelay(context.options.retry || 0)
|
|
1160
1240
|
});
|
|
@@ -1166,6 +1246,72 @@ class CloudClient {
|
|
|
1166
1246
|
getConfig() {
|
|
1167
1247
|
return { ...this.config };
|
|
1168
1248
|
}
|
|
1249
|
+
async registerDevice(payload) {
|
|
1250
|
+
if (!this.canSendUsageAnalytics()) {
|
|
1251
|
+
return {
|
|
1252
|
+
success: false,
|
|
1253
|
+
message: "Usage analytics disabled"
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
try {
|
|
1257
|
+
return await this.fetch("/device/register", {
|
|
1258
|
+
method: "POST",
|
|
1259
|
+
body: this.buildAnalyticsPayload(payload),
|
|
1260
|
+
timeout: 5e3
|
|
1261
|
+
});
|
|
1262
|
+
} catch (error) {
|
|
1263
|
+
consola.debug("Failed to register device (non-blocking):", error);
|
|
1264
|
+
return {
|
|
1265
|
+
success: false,
|
|
1266
|
+
requestId: "",
|
|
1267
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
async handshake(payload) {
|
|
1272
|
+
if (!this.canSendUsageAnalytics()) {
|
|
1273
|
+
return {
|
|
1274
|
+
success: false,
|
|
1275
|
+
message: "Usage analytics disabled"
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
try {
|
|
1279
|
+
return await this.fetch(`${API_PREFIX}/handshake`, {
|
|
1280
|
+
method: "POST",
|
|
1281
|
+
body: this.buildAnalyticsPayload(payload),
|
|
1282
|
+
timeout: 5e3
|
|
1283
|
+
});
|
|
1284
|
+
} catch (error) {
|
|
1285
|
+
consola.debug("Failed to send handshake (non-blocking):", error);
|
|
1286
|
+
return {
|
|
1287
|
+
success: false,
|
|
1288
|
+
requestId: "",
|
|
1289
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
1290
|
+
};
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
async syncClientUsage(payload) {
|
|
1294
|
+
if (!this.canSendUsageAnalytics()) {
|
|
1295
|
+
return {
|
|
1296
|
+
success: false,
|
|
1297
|
+
message: "Usage analytics disabled"
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
try {
|
|
1301
|
+
return await this.fetch(`${API_PREFIX}/sync`, {
|
|
1302
|
+
method: "POST",
|
|
1303
|
+
body: this.buildAnalyticsPayload(payload),
|
|
1304
|
+
timeout: 5e3
|
|
1305
|
+
});
|
|
1306
|
+
} catch (error) {
|
|
1307
|
+
consola.debug("Failed to sync client usage (non-blocking):", error);
|
|
1308
|
+
return {
|
|
1309
|
+
success: false,
|
|
1310
|
+
requestId: "",
|
|
1311
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1169
1315
|
}
|
|
1170
1316
|
function createCloudClient(config) {
|
|
1171
1317
|
return new CloudClient({
|
|
@@ -1337,7 +1483,7 @@ class TelemetryReporter {
|
|
|
1337
1483
|
constructor(client, config = {}) {
|
|
1338
1484
|
this.client = client;
|
|
1339
1485
|
this.config = { ...DEFAULT_TELEMETRY_CONFIG, ...config };
|
|
1340
|
-
this.userId = this.config.userId || this.generateUserId();
|
|
1486
|
+
this.userId = this.config.userId || this.client.getIdentity().anonymousUserId || this.generateUserId();
|
|
1341
1487
|
if (this.config.enabled) {
|
|
1342
1488
|
this.startFlushTimer();
|
|
1343
1489
|
}
|
|
@@ -1578,6 +1724,11 @@ function initializeTelemetry(client, config) {
|
|
|
1578
1724
|
});
|
|
1579
1725
|
}
|
|
1580
1726
|
globalTelemetry = new TelemetryReporter(client, config);
|
|
1727
|
+
if (client.getConfig().autoHandshake !== false && client.getConfig().enableUsageAnalytics !== false) {
|
|
1728
|
+
client.handshake().catch((error) => {
|
|
1729
|
+
consola.debug("Failed to send startup handshake (non-blocking):", error);
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1581
1732
|
return globalTelemetry;
|
|
1582
1733
|
}
|
|
1583
1734
|
function getTelemetry() {
|
|
@@ -1680,6 +1831,15 @@ class FallbackCloudClient {
|
|
|
1680
1831
|
async reportUsage(report) {
|
|
1681
1832
|
return this.client.reportUsage(report);
|
|
1682
1833
|
}
|
|
1834
|
+
async registerDevice(payload) {
|
|
1835
|
+
return this.client.registerDevice(payload);
|
|
1836
|
+
}
|
|
1837
|
+
async handshake(payload) {
|
|
1838
|
+
return this.client.handshake(payload);
|
|
1839
|
+
}
|
|
1840
|
+
async syncClientUsage(payload) {
|
|
1841
|
+
return this.client.syncClientUsage(payload);
|
|
1842
|
+
}
|
|
1683
1843
|
/**
|
|
1684
1844
|
* Health check (no fallback)
|
|
1685
1845
|
*/
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccjk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "13.
|
|
5
|
-
"packageManager": "pnpm@10.17.1",
|
|
4
|
+
"version": "13.5.1",
|
|
6
5
|
"description": "Turn Claude Code into a production-ready AI dev environment with one-command setup, persistent memory, MCP automation, cloud sync, and zero-config browser workflows.",
|
|
7
6
|
"author": {
|
|
8
7
|
"name": "CCJK Team",
|
|
@@ -81,71 +80,6 @@
|
|
|
81
80
|
"engines": {
|
|
82
81
|
"node": ">=20"
|
|
83
82
|
},
|
|
84
|
-
"scripts": {
|
|
85
|
-
"dev": "tsx ./src/cli.ts",
|
|
86
|
-
"build": "unbuild",
|
|
87
|
-
"start": "node bin/ccjk.mjs",
|
|
88
|
-
"typecheck": "tsc --noEmit",
|
|
89
|
-
"release:verify": "node scripts/release-verify.mjs",
|
|
90
|
-
"release:verify:full": "node scripts/release-verify.mjs --with-tests",
|
|
91
|
-
"prepublishOnly": "node scripts/validate-prepublish.mjs && pnpm contract:check && pnpm build",
|
|
92
|
-
"lint": "eslint",
|
|
93
|
-
"lint:fix": "eslint --fix",
|
|
94
|
-
"test": "vitest",
|
|
95
|
-
"test:ui": "vitest --ui",
|
|
96
|
-
"test:coverage": "vitest run --coverage",
|
|
97
|
-
"test:run": "vitest run",
|
|
98
|
-
"test:watch": "vitest watch",
|
|
99
|
-
"test:e2e": "NODE_ENV=test vitest --config vitest.e2e.config.ts",
|
|
100
|
-
"test:e2e:run": "NODE_ENV=test vitest run --config vitest.e2e.config.ts",
|
|
101
|
-
"test:e2e:ui": "NODE_ENV=test vitest --config vitest.e2e.config.ts --ui",
|
|
102
|
-
"test:e2e:coverage": "NODE_ENV=test vitest run --config vitest.e2e.config.ts --coverage",
|
|
103
|
-
"test:e2e:debug": "NODE_ENV=test CCJK_E2E_DEBUG=true vitest --config vitest.e2e.config.ts",
|
|
104
|
-
"test:v2": "vitest --config vitest.config.v2.ts",
|
|
105
|
-
"test:v2:ui": "vitest --config vitest.config.v2.ts --ui",
|
|
106
|
-
"test:v2:coverage": "vitest run --config vitest.config.v2.ts --coverage",
|
|
107
|
-
"test:v2:run": "vitest run --config vitest.config.v2.ts",
|
|
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",
|
|
113
|
-
"prepare": "husky",
|
|
114
|
-
"format": "prettier --write src/**/*.ts",
|
|
115
|
-
"prepublish:fix": "node scripts/fix-package-catalog.mjs",
|
|
116
|
-
"cleanup": "node scripts/cleanup.js",
|
|
117
|
-
"cleanup:auto": "node scripts/cleanup.js --auto",
|
|
118
|
-
"cleanup:dry": "node scripts/cleanup.js --dry-run",
|
|
119
|
-
"clean": "rm -rf dist coverage .turbo *.tsbuildinfo",
|
|
120
|
-
"benchmark:compression": "tsx scripts/benchmark-compression.ts",
|
|
121
|
-
"v2:setup": "chmod +x scripts/v2-dev-setup.sh && ./scripts/v2-dev-setup.sh",
|
|
122
|
-
"v2:setup:skip-tests": "chmod +x scripts/v2-dev-setup.sh && ./scripts/v2-dev-setup.sh --skip-tests",
|
|
123
|
-
"v2:services:up": "docker-compose -f docker-compose.dev.yml up -d",
|
|
124
|
-
"v2:services:down": "docker-compose -f docker-compose.dev.yml down",
|
|
125
|
-
"v2:services:restart": "docker-compose -f docker-compose.dev.yml restart",
|
|
126
|
-
"v2:services:logs": "docker-compose -f docker-compose.dev.yml logs -f",
|
|
127
|
-
"v2:services:status": "docker-compose -f docker-compose.dev.yml ps",
|
|
128
|
-
"v2:db:reset": "docker-compose -f docker-compose.dev.yml down postgres && docker volume rm ccjk-public_postgres_data && docker-compose -f docker-compose.dev.yml up -d postgres",
|
|
129
|
-
"v2:db:migrate": "echo 'Database migration script - to be implemented'",
|
|
130
|
-
"v2:db:seed": "echo 'Database seeding script - to be implemented'",
|
|
131
|
-
"v2:cache:clear": "docker exec ccjk-redis-dev redis-cli FLUSHALL",
|
|
132
|
-
"v2:search:reindex": "curl -X DELETE http://localhost:9200/ccjk_dev* && echo 'Elasticsearch indexes cleared'",
|
|
133
|
-
"v2:health": "chmod +x scripts/health-check.sh && ./scripts/health-check.sh",
|
|
134
|
-
"v2:dev": "concurrently \"pnpm v2:services:up\" \"pnpm dev\"",
|
|
135
|
-
"v2:test:integration": "NODE_ENV=test pnpm test -- --config vitest.integration.config.ts",
|
|
136
|
-
"v2:test:e2e": "NODE_ENV=test pnpm test -- --config vitest.e2e.config.ts",
|
|
137
|
-
"v2:monitoring:up": "docker-compose -f docker-compose.dev.yml --profile monitoring up -d",
|
|
138
|
-
"v2:tracing:up": "docker-compose -f docker-compose.dev.yml --profile tracing up -d",
|
|
139
|
-
"v2:clean": "pnpm clean && docker-compose -f docker-compose.dev.yml down -v && docker system prune -f",
|
|
140
|
-
"benchmark": "tsx src/v2/__tests__/benchmarks.ts",
|
|
141
|
-
"benchmark:save": "tsx src/v2/__tests__/benchmarks.ts && echo 'Results saved to .ccjk/benchmark-results.json'",
|
|
142
|
-
"benchmark:detailed": "tsx src/v2/__tests__/benchmarks.ts --detailed",
|
|
143
|
-
"benchmark:server": "npx http-server docs/v2 -p 8080 -o dashboard.html",
|
|
144
|
-
"benchmark:open": "open docs/v2/dashboard.html || xdg-open docs/v2/dashboard.html || start docs/v2/dashboard.html",
|
|
145
|
-
"i18n:check": "tsx scripts/check-i18n.ts",
|
|
146
|
-
"i18n:report": "tsx scripts/check-i18n.ts --report",
|
|
147
|
-
"contract:check": "node scripts/check-remote-contract.mjs"
|
|
148
|
-
},
|
|
149
83
|
"dependencies": {
|
|
150
84
|
"better-sqlite3": "^12.6.2",
|
|
151
85
|
"fdir": "^6.5.0",
|
|
@@ -208,5 +142,68 @@
|
|
|
208
142
|
"unbuild": "^3.6.1",
|
|
209
143
|
"uuid": "^11.1.0",
|
|
210
144
|
"vitest": "^3.2.4"
|
|
145
|
+
},
|
|
146
|
+
"scripts": {
|
|
147
|
+
"dev": "tsx ./src/cli.ts",
|
|
148
|
+
"build": "unbuild",
|
|
149
|
+
"start": "node bin/ccjk.mjs",
|
|
150
|
+
"typecheck": "tsc --noEmit",
|
|
151
|
+
"release:verify": "node scripts/release-verify.mjs",
|
|
152
|
+
"release:verify:full": "node scripts/release-verify.mjs --with-tests",
|
|
153
|
+
"lint": "eslint",
|
|
154
|
+
"lint:fix": "eslint --fix",
|
|
155
|
+
"test": "vitest",
|
|
156
|
+
"test:ui": "vitest --ui",
|
|
157
|
+
"test:coverage": "vitest run --coverage",
|
|
158
|
+
"test:run": "vitest run",
|
|
159
|
+
"test:watch": "vitest watch",
|
|
160
|
+
"test:e2e": "NODE_ENV=test vitest --config vitest.e2e.config.ts",
|
|
161
|
+
"test:e2e:run": "NODE_ENV=test vitest run --config vitest.e2e.config.ts",
|
|
162
|
+
"test:e2e:ui": "NODE_ENV=test vitest --config vitest.e2e.config.ts --ui",
|
|
163
|
+
"test:e2e:coverage": "NODE_ENV=test vitest run --config vitest.e2e.config.ts --coverage",
|
|
164
|
+
"test:e2e:debug": "NODE_ENV=test CCJK_E2E_DEBUG=true vitest --config vitest.e2e.config.ts",
|
|
165
|
+
"test:v2": "vitest --config vitest.config.v2.ts",
|
|
166
|
+
"test:v2:ui": "vitest --config vitest.config.v2.ts --ui",
|
|
167
|
+
"test:v2:coverage": "vitest run --config vitest.config.v2.ts --coverage",
|
|
168
|
+
"test:v2:run": "vitest run --config vitest.config.v2.ts",
|
|
169
|
+
"test:v2:watch": "vitest watch --config vitest.config.v2.ts",
|
|
170
|
+
"test:integration": "NODE_ENV=test vitest --config vitest.integration.config.ts",
|
|
171
|
+
"test:integration:run": "NODE_ENV=test vitest run --config vitest.integration.config.ts",
|
|
172
|
+
"test:integration:ui": "NODE_ENV=test vitest --config vitest.integration.config.ts --ui",
|
|
173
|
+
"test:integration:coverage": "NODE_ENV=test vitest run --config vitest.integration.config.ts --coverage",
|
|
174
|
+
"format": "prettier --write src/**/*.ts",
|
|
175
|
+
"prepublish:fix": "node scripts/fix-package-catalog.mjs",
|
|
176
|
+
"cleanup": "node scripts/cleanup.js",
|
|
177
|
+
"cleanup:auto": "node scripts/cleanup.js --auto",
|
|
178
|
+
"cleanup:dry": "node scripts/cleanup.js --dry-run",
|
|
179
|
+
"clean": "rm -rf dist coverage .turbo *.tsbuildinfo",
|
|
180
|
+
"benchmark:compression": "tsx scripts/benchmark-compression.ts",
|
|
181
|
+
"v2:setup": "chmod +x scripts/v2-dev-setup.sh && ./scripts/v2-dev-setup.sh",
|
|
182
|
+
"v2:setup:skip-tests": "chmod +x scripts/v2-dev-setup.sh && ./scripts/v2-dev-setup.sh --skip-tests",
|
|
183
|
+
"v2:services:up": "docker-compose -f docker-compose.dev.yml up -d",
|
|
184
|
+
"v2:services:down": "docker-compose -f docker-compose.dev.yml down",
|
|
185
|
+
"v2:services:restart": "docker-compose -f docker-compose.dev.yml restart",
|
|
186
|
+
"v2:services:logs": "docker-compose -f docker-compose.dev.yml logs -f",
|
|
187
|
+
"v2:services:status": "docker-compose -f docker-compose.dev.yml ps",
|
|
188
|
+
"v2:db:reset": "docker-compose -f docker-compose.dev.yml down postgres && docker volume rm ccjk-public_postgres_data && docker-compose -f docker-compose.dev.yml up -d postgres",
|
|
189
|
+
"v2:db:migrate": "echo 'Database migration script - to be implemented'",
|
|
190
|
+
"v2:db:seed": "echo 'Database seeding script - to be implemented'",
|
|
191
|
+
"v2:cache:clear": "docker exec ccjk-redis-dev redis-cli FLUSHALL",
|
|
192
|
+
"v2:search:reindex": "curl -X DELETE http://localhost:9200/ccjk_dev* && echo 'Elasticsearch indexes cleared'",
|
|
193
|
+
"v2:health": "chmod +x scripts/health-check.sh && ./scripts/health-check.sh",
|
|
194
|
+
"v2:dev": "concurrently \"pnpm v2:services:up\" \"pnpm dev\"",
|
|
195
|
+
"v2:test:integration": "NODE_ENV=test pnpm test -- --config vitest.integration.config.ts",
|
|
196
|
+
"v2:test:e2e": "NODE_ENV=test pnpm test -- --config vitest.e2e.config.ts",
|
|
197
|
+
"v2:monitoring:up": "docker-compose -f docker-compose.dev.yml --profile monitoring up -d",
|
|
198
|
+
"v2:tracing:up": "docker-compose -f docker-compose.dev.yml --profile tracing up -d",
|
|
199
|
+
"v2:clean": "pnpm clean && docker-compose -f docker-compose.dev.yml down -v && docker system prune -f",
|
|
200
|
+
"benchmark": "tsx src/v2/__tests__/benchmarks.ts",
|
|
201
|
+
"benchmark:save": "tsx src/v2/__tests__/benchmarks.ts && echo 'Results saved to .ccjk/benchmark-results.json'",
|
|
202
|
+
"benchmark:detailed": "tsx src/v2/__tests__/benchmarks.ts --detailed",
|
|
203
|
+
"benchmark:server": "npx http-server docs/v2 -p 8080 -o dashboard.html",
|
|
204
|
+
"benchmark:open": "open docs/v2/dashboard.html || xdg-open docs/v2/dashboard.html || start docs/v2/dashboard.html",
|
|
205
|
+
"i18n:check": "tsx scripts/check-i18n.ts",
|
|
206
|
+
"i18n:report": "tsx scripts/check-i18n.ts --report",
|
|
207
|
+
"contract:check": "node scripts/check-remote-contract.mjs"
|
|
211
208
|
}
|
|
212
|
-
}
|
|
209
|
+
}
|