ccjk 12.0.7 → 12.0.8
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/package.json +1 -1
- package/dist/chunks/agent-teams.mjs +0 -136
- package/dist/chunks/agent.mjs +0 -1439
- package/dist/chunks/agents.mjs +0 -3778
- package/dist/chunks/api-cli.mjs +0 -132
- package/dist/chunks/api-providers.mjs +0 -129
- package/dist/chunks/api.mjs +0 -112
- package/dist/chunks/auto-bootstrap.mjs +0 -358
- package/dist/chunks/auto-init.mjs +0 -7584
- package/dist/chunks/auto-updater.mjs +0 -410
- package/dist/chunks/banner.mjs +0 -188
- package/dist/chunks/bash.mjs +0 -187
- package/dist/chunks/boost.mjs +0 -397
- package/dist/chunks/ccjk-agents.mjs +0 -414
- package/dist/chunks/ccjk-all.mjs +0 -1028
- package/dist/chunks/ccjk-config.mjs +0 -261
- package/dist/chunks/ccjk-hooks.mjs +0 -1074
- package/dist/chunks/ccjk-mcp.mjs +0 -761
- package/dist/chunks/ccjk-setup.mjs +0 -763
- package/dist/chunks/ccjk-skills.mjs +0 -514
- package/dist/chunks/ccr.mjs +0 -98
- package/dist/chunks/ccu.mjs +0 -40
- package/dist/chunks/check-updates.mjs +0 -108
- package/dist/chunks/claude-code-config-manager.mjs +0 -750
- package/dist/chunks/claude-code-incremental-manager.mjs +0 -623
- package/dist/chunks/claude-config.mjs +0 -236
- package/dist/chunks/claude-wrapper.mjs +0 -85
- package/dist/chunks/cleanup-migration.mjs +0 -20
- package/dist/chunks/cli-hook.mjs +0 -2285
- package/dist/chunks/cloud-sync.mjs +0 -29
- package/dist/chunks/codex-config-switch.mjs +0 -451
- package/dist/chunks/codex-provider-manager.mjs +0 -236
- package/dist/chunks/codex-uninstaller.mjs +0 -404
- package/dist/chunks/codex.mjs +0 -2077
- package/dist/chunks/commands.mjs +0 -108
- package/dist/chunks/commands2.mjs +0 -413
- package/dist/chunks/commit.mjs +0 -138
- package/dist/chunks/completion.mjs +0 -515
- package/dist/chunks/config-consolidator.mjs +0 -172
- package/dist/chunks/config-switch.mjs +0 -317
- package/dist/chunks/config.mjs +0 -379
- package/dist/chunks/config2.mjs +0 -477
- package/dist/chunks/config3.mjs +0 -470
- package/dist/chunks/constants.mjs +0 -133
- package/dist/chunks/context-loader.mjs +0 -343
- package/dist/chunks/context.mjs +0 -372
- package/dist/chunks/convoy-manager.mjs +0 -880
- package/dist/chunks/dashboard.mjs +0 -476
- package/dist/chunks/doctor.mjs +0 -964
- package/dist/chunks/evolution.mjs +0 -382
- package/dist/chunks/features.mjs +0 -698
- package/dist/chunks/fish.mjs +0 -181
- package/dist/chunks/fs-operations.mjs +0 -192
- package/dist/chunks/health-alerts.mjs +0 -304
- package/dist/chunks/health-check.mjs +0 -532
- package/dist/chunks/help.mjs +0 -340
- package/dist/chunks/hook-installer.mjs +0 -45
- package/dist/chunks/index.mjs +0 -24
- package/dist/chunks/index10.mjs +0 -1171
- package/dist/chunks/index11.mjs +0 -1008
- package/dist/chunks/index12.mjs +0 -193
- package/dist/chunks/index13.mjs +0 -218
- package/dist/chunks/index14.mjs +0 -663
- package/dist/chunks/index2.mjs +0 -19
- package/dist/chunks/index3.mjs +0 -19092
- package/dist/chunks/index4.mjs +0 -8
- package/dist/chunks/index5.mjs +0 -7600
- package/dist/chunks/index6.mjs +0 -171
- package/dist/chunks/index7.mjs +0 -3583
- package/dist/chunks/index8.mjs +0 -19
- package/dist/chunks/index9.mjs +0 -616
- package/dist/chunks/init.mjs +0 -1606
- package/dist/chunks/installer.mjs +0 -690
- package/dist/chunks/installer2.mjs +0 -179
- package/dist/chunks/interview.mjs +0 -2927
- package/dist/chunks/json-config.mjs +0 -60
- package/dist/chunks/linux.mjs +0 -3863
- package/dist/chunks/macos.mjs +0 -69
- package/dist/chunks/main.mjs +0 -635
- package/dist/chunks/manager.mjs +0 -1048
- package/dist/chunks/marketplace.mjs +0 -949
- package/dist/chunks/mcp-cli.mjs +0 -204
- package/dist/chunks/mcp-performance.mjs +0 -187
- package/dist/chunks/mcp.mjs +0 -1231
- package/dist/chunks/menu.mjs +0 -652
- package/dist/chunks/metrics-display.mjs +0 -153
- package/dist/chunks/migrator.mjs +0 -178
- package/dist/chunks/monitor.mjs +0 -1856
- package/dist/chunks/notification.mjs +0 -1864
- package/dist/chunks/onboarding.mjs +0 -385
- package/dist/chunks/package.mjs +0 -3
- package/dist/chunks/paradigm.mjs +0 -74
- package/dist/chunks/permission-manager.mjs +0 -132
- package/dist/chunks/permissions.mjs +0 -265
- package/dist/chunks/persistence-manager.mjs +0 -794
- package/dist/chunks/persistence.mjs +0 -667
- package/dist/chunks/platform.mjs +0 -391
- package/dist/chunks/plugin.mjs +0 -1936
- package/dist/chunks/powershell.mjs +0 -213
- package/dist/chunks/prompts.mjs +0 -241
- package/dist/chunks/providers.mjs +0 -260
- package/dist/chunks/quick-actions.mjs +0 -320
- package/dist/chunks/quick-provider.mjs +0 -682
- package/dist/chunks/quick-setup.mjs +0 -412
- package/dist/chunks/remote.mjs +0 -497
- package/dist/chunks/session.mjs +0 -878
- package/dist/chunks/sessions.mjs +0 -106
- package/dist/chunks/silent-updater.mjs +0 -396
- package/dist/chunks/simple-config.mjs +0 -98
- package/dist/chunks/skill.mjs +0 -117
- package/dist/chunks/skill2.mjs +0 -9003
- package/dist/chunks/skills-sync.mjs +0 -6460
- package/dist/chunks/skills.mjs +0 -567
- package/dist/chunks/slash-commands.mjs +0 -207
- package/dist/chunks/smart-defaults.mjs +0 -412
- package/dist/chunks/smart-guide.mjs +0 -194
- package/dist/chunks/startup.mjs +0 -487
- package/dist/chunks/stats.mjs +0 -410
- package/dist/chunks/status.mjs +0 -289
- package/dist/chunks/team.mjs +0 -63
- package/dist/chunks/thinking.mjs +0 -626
- package/dist/chunks/trace.mjs +0 -57
- package/dist/chunks/uninstall.mjs +0 -849
- package/dist/chunks/update.mjs +0 -167
- package/dist/chunks/upgrade-manager.mjs +0 -204
- package/dist/chunks/version-checker.mjs +0 -881
- package/dist/chunks/vim.mjs +0 -903
- package/dist/chunks/windows.mjs +0 -14
- package/dist/chunks/workflows.mjs +0 -633
- package/dist/chunks/wsl.mjs +0 -129
- package/dist/chunks/zero-config.mjs +0 -374
- package/dist/chunks/zsh.mjs +0 -182
- package/dist/cli.d.mts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.mjs +0 -2199
- package/dist/i18n/locales/en/agent-teams.json +0 -18
- package/dist/i18n/locales/en/agentBrowser.json +0 -79
- package/dist/i18n/locales/en/agents.json +0 -135
- package/dist/i18n/locales/en/api.json +0 -63
- package/dist/i18n/locales/en/ccjk-agents.json +0 -33
- package/dist/i18n/locales/en/ccjk-all.json +0 -23
- package/dist/i18n/locales/en/ccjk-skills.json +0 -22
- package/dist/i18n/locales/en/ccjk.json +0 -276
- package/dist/i18n/locales/en/ccr.json +0 -65
- package/dist/i18n/locales/en/claude-md.json +0 -73
- package/dist/i18n/locales/en/cli.json +0 -152
- package/dist/i18n/locales/en/cloud-setup.json +0 -31
- package/dist/i18n/locales/en/cloud-sync.json +0 -147
- package/dist/i18n/locales/en/cloud.json +0 -40
- package/dist/i18n/locales/en/cloudPlugins.json +0 -118
- package/dist/i18n/locales/en/codex.json +0 -127
- package/dist/i18n/locales/en/cometix.json +0 -29
- package/dist/i18n/locales/en/common.json +0 -68
- package/dist/i18n/locales/en/config.json +0 -108
- package/dist/i18n/locales/en/configuration.json +0 -226
- package/dist/i18n/locales/en/context.json +0 -85
- package/dist/i18n/locales/en/dashboard.json +0 -78
- package/dist/i18n/locales/en/errors.json +0 -26
- package/dist/i18n/locales/en/evolution.json +0 -54
- package/dist/i18n/locales/en/hooks.json +0 -74
- package/dist/i18n/locales/en/hooksSync.json +0 -133
- package/dist/i18n/locales/en/installation.json +0 -83
- package/dist/i18n/locales/en/interview.json +0 -104
- package/dist/i18n/locales/en/language.json +0 -19
- package/dist/i18n/locales/en/lsp.json +0 -78
- package/dist/i18n/locales/en/marketplace.json +0 -116
- package/dist/i18n/locales/en/mcp.json +0 -178
- package/dist/i18n/locales/en/memory.json +0 -92
- package/dist/i18n/locales/en/menu.json +0 -143
- package/dist/i18n/locales/en/multi-config.json +0 -79
- package/dist/i18n/locales/en/notification.json +0 -307
- package/dist/i18n/locales/en/permissions.json +0 -95
- package/dist/i18n/locales/en/persistence.json +0 -127
- package/dist/i18n/locales/en/plugins.json +0 -146
- package/dist/i18n/locales/en/quick-actions.json +0 -78
- package/dist/i18n/locales/en/registry.json +0 -54
- package/dist/i18n/locales/en/remote.json +0 -93
- package/dist/i18n/locales/en/sandbox.json +0 -44
- package/dist/i18n/locales/en/setup.json +0 -44
- package/dist/i18n/locales/en/shencha.json +0 -14
- package/dist/i18n/locales/en/skills.json +0 -100
- package/dist/i18n/locales/en/skillsSync.json +0 -74
- package/dist/i18n/locales/en/smartGuide.json +0 -49
- package/dist/i18n/locales/en/stats.json +0 -20
- package/dist/i18n/locales/en/subagent.json +0 -69
- package/dist/i18n/locales/en/superpowers.json +0 -117
- package/dist/i18n/locales/en/team.json +0 -7
- package/dist/i18n/locales/en/thinking.json +0 -65
- package/dist/i18n/locales/en/tools.json +0 -42
- package/dist/i18n/locales/en/uninstall.json +0 -56
- package/dist/i18n/locales/en/updater.json +0 -29
- package/dist/i18n/locales/en/vim.json +0 -169
- package/dist/i18n/locales/en/workflow.json +0 -55
- package/dist/i18n/locales/en/workspace.json +0 -108
- package/dist/i18n/locales/zh-CN/agent-teams.json +0 -18
- package/dist/i18n/locales/zh-CN/agentBrowser.json +0 -79
- package/dist/i18n/locales/zh-CN/agents.json +0 -135
- package/dist/i18n/locales/zh-CN/api.json +0 -63
- package/dist/i18n/locales/zh-CN/ccjk-agents.json +0 -33
- package/dist/i18n/locales/zh-CN/ccjk-all.json +0 -23
- package/dist/i18n/locales/zh-CN/ccjk-skills.json +0 -22
- package/dist/i18n/locales/zh-CN/ccjk.json +0 -276
- package/dist/i18n/locales/zh-CN/ccr.json +0 -65
- package/dist/i18n/locales/zh-CN/claude-md.json +0 -73
- package/dist/i18n/locales/zh-CN/cli.json +0 -152
- package/dist/i18n/locales/zh-CN/cloud-setup.json +0 -31
- package/dist/i18n/locales/zh-CN/cloud-sync.json +0 -147
- package/dist/i18n/locales/zh-CN/cloud.json +0 -40
- package/dist/i18n/locales/zh-CN/cloudPlugins.json +0 -118
- package/dist/i18n/locales/zh-CN/codex.json +0 -127
- package/dist/i18n/locales/zh-CN/cometix.json +0 -29
- package/dist/i18n/locales/zh-CN/common.json +0 -68
- package/dist/i18n/locales/zh-CN/config.json +0 -108
- package/dist/i18n/locales/zh-CN/configuration.json +0 -224
- package/dist/i18n/locales/zh-CN/context.json +0 -85
- package/dist/i18n/locales/zh-CN/dashboard.json +0 -78
- package/dist/i18n/locales/zh-CN/errors.json +0 -26
- package/dist/i18n/locales/zh-CN/evolution.json +0 -54
- package/dist/i18n/locales/zh-CN/hooks.json +0 -74
- package/dist/i18n/locales/zh-CN/hooksSync.json +0 -133
- package/dist/i18n/locales/zh-CN/installation.json +0 -83
- package/dist/i18n/locales/zh-CN/interview.json +0 -104
- package/dist/i18n/locales/zh-CN/language.json +0 -19
- package/dist/i18n/locales/zh-CN/lsp.json +0 -78
- package/dist/i18n/locales/zh-CN/marketplace.json +0 -116
- package/dist/i18n/locales/zh-CN/mcp.json +0 -178
- package/dist/i18n/locales/zh-CN/memory.json +0 -92
- package/dist/i18n/locales/zh-CN/menu.json +0 -143
- package/dist/i18n/locales/zh-CN/multi-config.json +0 -79
- package/dist/i18n/locales/zh-CN/notification.json +0 -307
- package/dist/i18n/locales/zh-CN/permissions.json +0 -95
- package/dist/i18n/locales/zh-CN/persistence.json +0 -127
- package/dist/i18n/locales/zh-CN/plugins.json +0 -146
- package/dist/i18n/locales/zh-CN/quick-actions.json +0 -78
- package/dist/i18n/locales/zh-CN/registry.json +0 -54
- package/dist/i18n/locales/zh-CN/remote.json +0 -93
- package/dist/i18n/locales/zh-CN/sandbox.json +0 -44
- package/dist/i18n/locales/zh-CN/setup.json +0 -44
- package/dist/i18n/locales/zh-CN/shencha.json +0 -14
- package/dist/i18n/locales/zh-CN/skills.json +0 -100
- package/dist/i18n/locales/zh-CN/skillsSync.json +0 -74
- package/dist/i18n/locales/zh-CN/smartGuide.json +0 -49
- package/dist/i18n/locales/zh-CN/stats.json +0 -20
- package/dist/i18n/locales/zh-CN/subagent.json +0 -69
- package/dist/i18n/locales/zh-CN/superpowers.json +0 -117
- package/dist/i18n/locales/zh-CN/team.json +0 -7
- package/dist/i18n/locales/zh-CN/thinking.json +0 -65
- package/dist/i18n/locales/zh-CN/tools.json +0 -42
- package/dist/i18n/locales/zh-CN/uninstall.json +0 -56
- package/dist/i18n/locales/zh-CN/updater.json +0 -29
- package/dist/i18n/locales/zh-CN/vim.json +0 -169
- package/dist/i18n/locales/zh-CN/workflow.json +0 -55
- package/dist/i18n/locales/zh-CN/workspace.json +0 -108
- package/dist/index.d.mts +0 -5295
- package/dist/index.d.ts +0 -5295
- package/dist/index.mjs +0 -4941
- package/dist/shared/ccjk.B364Fu0N.mjs +0 -1819
- package/dist/shared/ccjk.BAGoDD49.mjs +0 -36
- package/dist/shared/ccjk.BBtCGd_g.mjs +0 -899
- package/dist/shared/ccjk.BFQ7yr5S.mjs +0 -16
- package/dist/shared/ccjk.BFxsJM0k.mjs +0 -599
- package/dist/shared/ccjk.BIxuVL3_.mjs +0 -25
- package/dist/shared/ccjk.BRZ9ww8S.mjs +0 -142
- package/dist/shared/ccjk.BoApaI4j.mjs +0 -28
- package/dist/shared/ccjk.BrPUmTqm.mjs +0 -266
- package/dist/shared/ccjk.BtB1e5jm.mjs +0 -171
- package/dist/shared/ccjk.BwfbSKN2.mjs +0 -1051
- package/dist/shared/ccjk.BxSmJ8B7.mjs +0 -243
- package/dist/shared/ccjk.Bx_rmYfN.mjs +0 -69
- package/dist/shared/ccjk.C2jHOZVP.mjs +0 -52
- package/dist/shared/ccjk.CL4Yat0G.mjs +0 -303
- package/dist/shared/ccjk.COweQ1RR.mjs +0 -5
- package/dist/shared/ccjk.CePkJq2S.mjs +0 -223
- package/dist/shared/ccjk.CfKKcvWy.mjs +0 -126
- package/dist/shared/ccjk.Cjgrln_h.mjs +0 -297
- package/dist/shared/ccjk.Cjj8SVrn.mjs +0 -54
- package/dist/shared/ccjk.CxpGa6MC.mjs +0 -2724
- package/dist/shared/ccjk.D5MFQT7w.mjs +0 -400
- package/dist/shared/ccjk.D6ycHbak.mjs +0 -270
- package/dist/shared/ccjk.D8ZLYSZZ.mjs +0 -299
- package/dist/shared/ccjk.DG_o24cZ.mjs +0 -88
- package/dist/shared/ccjk.DLLw-h4Y.mjs +0 -460
- package/dist/shared/ccjk.DOwtZMk8.mjs +0 -4019
- package/dist/shared/ccjk.DS7UESmF.mjs +0 -2451
- package/dist/shared/ccjk.DTdjs-qK.mjs +0 -1447
- package/dist/shared/ccjk.DXRAZcix.mjs +0 -66
- package/dist/shared/ccjk.DsYaCCx4.mjs +0 -317
- package/dist/shared/ccjk.J8YiPsOw.mjs +0 -259
- package/dist/shared/ccjk.KfSWcGlE.mjs +0 -38
- package/dist/shared/ccjk.RyizuzOI.mjs +0 -21
- package/dist/shared/ccjk.SPoXMvZD.mjs +0 -1242
- package/dist/shared/ccjk.T_cX87dY.mjs +0 -15
- package/dist/shared/ccjk.UIvifqNE.mjs +0 -1486
- package/dist/shared/ccjk._dESH4Rk.mjs +0 -111
- package/dist/shared/ccjk.bQ7Dh1g4.mjs +0 -249
- package/dist/shared/ccjk.c-ETfBZ_.mjs +0 -617
- package/dist/shared/ccjk.gDEDGD_t.mjs +0 -38
- package/dist/shared/ccjk.hoqrwWdN.mjs +0 -333
- package/dist/shared/ccjk.waa2ikKJ.mjs +0 -351
package/dist/chunks/doctor.mjs
DELETED
|
@@ -1,964 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, statSync, writeFileSync, readFileSync, copyFileSync, readdirSync } from 'node:fs';
|
|
2
|
-
import process__default from 'node:process';
|
|
3
|
-
import a from './index2.mjs';
|
|
4
|
-
import { i as inquirer } from './index3.mjs';
|
|
5
|
-
import { getApiProviderPresets } from './api-providers.mjs';
|
|
6
|
-
import { SETTINGS_FILE, CLAUDE_DIR } from './constants.mjs';
|
|
7
|
-
import { i18n } from './index5.mjs';
|
|
8
|
-
import { g as getPermissionManager } from '../shared/ccjk.SPoXMvZD.mjs';
|
|
9
|
-
import { h as commandExists } from './platform.mjs';
|
|
10
|
-
import { P as ProviderHealthMonitor } from '../shared/ccjk.J8YiPsOw.mjs';
|
|
11
|
-
import { platform, userInfo, homedir } from 'node:os';
|
|
12
|
-
import ora from './index7.mjs';
|
|
13
|
-
import { exec as q } from './main.mjs';
|
|
14
|
-
import { STATUS } from './banner.mjs';
|
|
15
|
-
import { writeFileAtomic } from './fs-operations.mjs';
|
|
16
|
-
import { c as resolve, j as join, d as dirname } from '../shared/ccjk.bQ7Dh1g4.mjs';
|
|
17
|
-
import '../shared/ccjk.BAGoDD49.mjs';
|
|
18
|
-
import 'node:readline';
|
|
19
|
-
import 'stream';
|
|
20
|
-
import 'node:tty';
|
|
21
|
-
import 'node:async_hooks';
|
|
22
|
-
import '../shared/ccjk.Cjgrln_h.mjs';
|
|
23
|
-
import 'node:util';
|
|
24
|
-
import 'tty';
|
|
25
|
-
import 'fs';
|
|
26
|
-
import 'child_process';
|
|
27
|
-
import 'node:path';
|
|
28
|
-
import 'node:crypto';
|
|
29
|
-
import 'buffer';
|
|
30
|
-
import 'string_decoder';
|
|
31
|
-
import 'node:url';
|
|
32
|
-
import 'module';
|
|
33
|
-
import 'node:child_process';
|
|
34
|
-
import 'node:stream';
|
|
35
|
-
import '../shared/ccjk.gDEDGD_t.mjs';
|
|
36
|
-
import 'node:fs/promises';
|
|
37
|
-
|
|
38
|
-
const t = i18n.t.bind(i18n);
|
|
39
|
-
function getClaudeSettings() {
|
|
40
|
-
try {
|
|
41
|
-
if (existsSync(SETTINGS_FILE)) {
|
|
42
|
-
return JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
|
|
43
|
-
}
|
|
44
|
-
} catch {
|
|
45
|
-
}
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
function saveClaudeSettings(settings) {
|
|
49
|
-
try {
|
|
50
|
-
if (!existsSync(CLAUDE_DIR)) {
|
|
51
|
-
mkdirSync(CLAUDE_DIR, { recursive: true });
|
|
52
|
-
}
|
|
53
|
-
writeFileAtomic(SETTINGS_FILE, JSON.stringify(settings, null, 2));
|
|
54
|
-
return true;
|
|
55
|
-
} catch {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
async function checkWorkingDirectory(cwd) {
|
|
60
|
-
try {
|
|
61
|
-
if (!existsSync(cwd)) {
|
|
62
|
-
return {
|
|
63
|
-
name: t("workspace:checks.cwdExists"),
|
|
64
|
-
status: "fail",
|
|
65
|
-
message: t("workspace:status.notExists"),
|
|
66
|
-
details: cwd,
|
|
67
|
-
fixDescription: t("workspace:fixes.createDirectory"),
|
|
68
|
-
fix: async () => {
|
|
69
|
-
try {
|
|
70
|
-
mkdirSync(cwd, { recursive: true });
|
|
71
|
-
return true;
|
|
72
|
-
} catch {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
const stat = statSync(cwd);
|
|
79
|
-
if (!stat.isDirectory()) {
|
|
80
|
-
return {
|
|
81
|
-
name: t("workspace:checks.cwdExists"),
|
|
82
|
-
status: "fail",
|
|
83
|
-
message: t("workspace:status.notDirectory"),
|
|
84
|
-
details: cwd
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
return {
|
|
88
|
-
name: t("workspace:checks.cwdExists"),
|
|
89
|
-
status: "pass",
|
|
90
|
-
message: cwd
|
|
91
|
-
};
|
|
92
|
-
} catch (error) {
|
|
93
|
-
return {
|
|
94
|
-
name: t("workspace:checks.cwdExists"),
|
|
95
|
-
status: "fail",
|
|
96
|
-
message: t("workspace:status.accessError"),
|
|
97
|
-
details: error instanceof Error ? error.message : String(error)
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
async function checkWritePermission(cwd) {
|
|
102
|
-
const testFile = join(cwd, `.ccjk-write-test-${Date.now()}.tmp`);
|
|
103
|
-
try {
|
|
104
|
-
writeFileSync(testFile, "test", { mode: 420 });
|
|
105
|
-
const content = readFileSync(testFile, "utf-8");
|
|
106
|
-
if (content !== "test") {
|
|
107
|
-
throw new Error("Content mismatch");
|
|
108
|
-
}
|
|
109
|
-
const { unlinkSync } = await import('node:fs');
|
|
110
|
-
unlinkSync(testFile);
|
|
111
|
-
return {
|
|
112
|
-
name: t("workspace:checks.writePermission"),
|
|
113
|
-
status: "pass",
|
|
114
|
-
message: t("workspace:status.writable")
|
|
115
|
-
};
|
|
116
|
-
} catch (error) {
|
|
117
|
-
try {
|
|
118
|
-
const { unlinkSync } = await import('node:fs');
|
|
119
|
-
if (existsSync(testFile)) {
|
|
120
|
-
unlinkSync(testFile);
|
|
121
|
-
}
|
|
122
|
-
} catch {
|
|
123
|
-
}
|
|
124
|
-
const isPermissionError = error instanceof Error && (error.message.includes("EACCES") || error.message.includes("EPERM"));
|
|
125
|
-
if (isPermissionError) {
|
|
126
|
-
return {
|
|
127
|
-
name: t("workspace:checks.writePermission"),
|
|
128
|
-
status: "fail",
|
|
129
|
-
message: t("workspace:status.noWritePermission"),
|
|
130
|
-
details: error instanceof Error ? error.message : String(error),
|
|
131
|
-
fixDescription: t("workspace:fixes.fixPermission"),
|
|
132
|
-
fix: async () => {
|
|
133
|
-
try {
|
|
134
|
-
if (platform() !== "win32") {
|
|
135
|
-
await q("chmod", ["-R", "u+w", cwd], { throwOnError: true });
|
|
136
|
-
return true;
|
|
137
|
-
}
|
|
138
|
-
return false;
|
|
139
|
-
} catch {
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
return {
|
|
146
|
-
name: t("workspace:checks.writePermission"),
|
|
147
|
-
status: "fail",
|
|
148
|
-
message: t("workspace:status.writeTestFailed"),
|
|
149
|
-
details: error instanceof Error ? error.message : String(error)
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
async function checkDirectoryOwnership(cwd) {
|
|
154
|
-
if (platform() === "win32") {
|
|
155
|
-
return {
|
|
156
|
-
name: t("workspace:checks.ownership"),
|
|
157
|
-
status: "info",
|
|
158
|
-
message: t("workspace:status.skippedWindows")
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
try {
|
|
162
|
-
const stat = statSync(cwd);
|
|
163
|
-
const currentUid = process__default.getuid?.() ?? -1;
|
|
164
|
-
if (currentUid === -1) {
|
|
165
|
-
return {
|
|
166
|
-
name: t("workspace:checks.ownership"),
|
|
167
|
-
status: "info",
|
|
168
|
-
message: t("workspace:status.cannotCheck")
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
if (stat.uid !== currentUid) {
|
|
172
|
-
const user = userInfo();
|
|
173
|
-
return {
|
|
174
|
-
name: t("workspace:checks.ownership"),
|
|
175
|
-
status: "warn",
|
|
176
|
-
message: t("workspace:status.differentOwner"),
|
|
177
|
-
details: t("workspace:details.ownerMismatch", { currentUser: user.username, dirUid: stat.uid }),
|
|
178
|
-
fixDescription: t("workspace:fixes.changeOwner"),
|
|
179
|
-
fix: async () => {
|
|
180
|
-
try {
|
|
181
|
-
await q("sudo", ["chown", "-R", `${currentUid}:${process__default.getgid?.() ?? currentUid}`, cwd], { throwOnError: true });
|
|
182
|
-
return true;
|
|
183
|
-
} catch {
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
return {
|
|
190
|
-
name: t("workspace:checks.ownership"),
|
|
191
|
-
status: "pass",
|
|
192
|
-
message: t("workspace:status.correctOwner")
|
|
193
|
-
};
|
|
194
|
-
} catch (error) {
|
|
195
|
-
return {
|
|
196
|
-
name: t("workspace:checks.ownership"),
|
|
197
|
-
status: "info",
|
|
198
|
-
message: t("workspace:status.checkFailed"),
|
|
199
|
-
details: error instanceof Error ? error.message : String(error)
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
async function checkTrustedDirectories(cwd) {
|
|
204
|
-
const settings = getClaudeSettings();
|
|
205
|
-
if (!settings) {
|
|
206
|
-
return {
|
|
207
|
-
name: t("workspace:checks.trustedDirs"),
|
|
208
|
-
status: "info",
|
|
209
|
-
message: t("workspace:status.noSettings"),
|
|
210
|
-
fixDescription: t("workspace:fixes.createSettings"),
|
|
211
|
-
fix: async () => {
|
|
212
|
-
return saveClaudeSettings({
|
|
213
|
-
allowedDirectories: [cwd]
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
const allowedDirs = settings.allowedDirectories || [];
|
|
219
|
-
const isTrusted = allowedDirs.some((dir) => {
|
|
220
|
-
const normalizedDir = resolve(dir);
|
|
221
|
-
const normalizedCwd = resolve(cwd);
|
|
222
|
-
return normalizedCwd === normalizedDir || normalizedCwd.startsWith(`${normalizedDir}/`);
|
|
223
|
-
});
|
|
224
|
-
if (!isTrusted) {
|
|
225
|
-
return {
|
|
226
|
-
name: t("workspace:checks.trustedDirs"),
|
|
227
|
-
status: "warn",
|
|
228
|
-
message: t("workspace:status.notTrusted"),
|
|
229
|
-
details: t("workspace:details.trustedList", { dirs: allowedDirs.join(", ") || t("workspace:status.none") }),
|
|
230
|
-
fixDescription: t("workspace:fixes.addToTrusted"),
|
|
231
|
-
fix: async () => {
|
|
232
|
-
const newSettings = { ...settings };
|
|
233
|
-
const dirs = newSettings.allowedDirectories || [];
|
|
234
|
-
dirs.push(cwd);
|
|
235
|
-
newSettings.allowedDirectories = dirs;
|
|
236
|
-
return saveClaudeSettings(newSettings);
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
return {
|
|
241
|
-
name: t("workspace:checks.trustedDirs"),
|
|
242
|
-
status: "pass",
|
|
243
|
-
message: t("workspace:status.trusted")
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
async function checkPathCharacters(cwd) {
|
|
247
|
-
const problematicChars = /[<>:"|?*\x00-\x1F]/;
|
|
248
|
-
const hasSpaces = cwd.includes(" ");
|
|
249
|
-
const hasUnicode = /[^\x00-\x7F]/.test(cwd);
|
|
250
|
-
if (problematicChars.test(cwd)) {
|
|
251
|
-
return {
|
|
252
|
-
name: t("workspace:checks.pathChars"),
|
|
253
|
-
status: "fail",
|
|
254
|
-
message: t("workspace:status.invalidChars"),
|
|
255
|
-
details: t("workspace:details.avoidChars")
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
if (hasSpaces || hasUnicode) {
|
|
259
|
-
return {
|
|
260
|
-
name: t("workspace:checks.pathChars"),
|
|
261
|
-
status: "warn",
|
|
262
|
-
message: hasSpaces ? t("workspace:status.hasSpaces") : t("workspace:status.hasUnicode"),
|
|
263
|
-
details: t("workspace:details.mayHaveIssues")
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
return {
|
|
267
|
-
name: t("workspace:checks.pathChars"),
|
|
268
|
-
status: "pass",
|
|
269
|
-
message: t("workspace:status.pathOk")
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
async function checkHomeDirectory(cwd) {
|
|
273
|
-
const home = homedir();
|
|
274
|
-
const normalizedCwd = resolve(cwd);
|
|
275
|
-
const normalizedHome = resolve(home);
|
|
276
|
-
const isInHome = normalizedCwd.startsWith(normalizedHome);
|
|
277
|
-
if (!isInHome) {
|
|
278
|
-
const systemDirs = ["/usr", "/bin", "/sbin", "/etc", "/var", "/tmp", "/root"];
|
|
279
|
-
const isSystemDir = systemDirs.some((dir) => normalizedCwd.startsWith(dir));
|
|
280
|
-
if (isSystemDir) {
|
|
281
|
-
return {
|
|
282
|
-
name: t("workspace:checks.homeDir"),
|
|
283
|
-
status: "fail",
|
|
284
|
-
message: t("workspace:status.systemDir"),
|
|
285
|
-
details: t("workspace:details.dontUseSystemDir")
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
return {
|
|
289
|
-
name: t("workspace:checks.homeDir"),
|
|
290
|
-
status: "warn",
|
|
291
|
-
message: t("workspace:status.outsideHome"),
|
|
292
|
-
details: t("workspace:details.recommendHome", { home })
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
return {
|
|
296
|
-
name: t("workspace:checks.homeDir"),
|
|
297
|
-
status: "pass",
|
|
298
|
-
message: t("workspace:status.insideHome")
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
async function checkDiskSpace(cwd) {
|
|
302
|
-
if (platform() === "win32") {
|
|
303
|
-
return {
|
|
304
|
-
name: t("workspace:checks.diskSpace"),
|
|
305
|
-
status: "info",
|
|
306
|
-
message: t("workspace:status.skippedWindows")
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
try {
|
|
310
|
-
const result = await q("df", ["-h", cwd], { throwOnError: false });
|
|
311
|
-
const lines = result.stdout.trim().split("\n");
|
|
312
|
-
if (lines.length >= 2) {
|
|
313
|
-
const parts = lines[1].split(/\s+/);
|
|
314
|
-
const available = parts[3];
|
|
315
|
-
const usePercent = Number.parseInt(parts[4]);
|
|
316
|
-
if (usePercent > 95) {
|
|
317
|
-
return {
|
|
318
|
-
name: t("workspace:checks.diskSpace"),
|
|
319
|
-
status: "fail",
|
|
320
|
-
message: t("workspace:status.diskFull", { percent: usePercent }),
|
|
321
|
-
details: t("workspace:details.available", { space: available })
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
if (usePercent > 90) {
|
|
325
|
-
return {
|
|
326
|
-
name: t("workspace:checks.diskSpace"),
|
|
327
|
-
status: "warn",
|
|
328
|
-
message: t("workspace:status.diskLow", { percent: usePercent }),
|
|
329
|
-
details: t("workspace:details.available", { space: available })
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
return {
|
|
333
|
-
name: t("workspace:checks.diskSpace"),
|
|
334
|
-
status: "pass",
|
|
335
|
-
message: t("workspace:details.available", { space: available })
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
return {
|
|
339
|
-
name: t("workspace:checks.diskSpace"),
|
|
340
|
-
status: "info",
|
|
341
|
-
message: t("workspace:status.cannotCheck")
|
|
342
|
-
};
|
|
343
|
-
} catch {
|
|
344
|
-
return {
|
|
345
|
-
name: t("workspace:checks.diskSpace"),
|
|
346
|
-
status: "info",
|
|
347
|
-
message: t("workspace:status.checkFailed")
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
async function checkParentDirectory(cwd) {
|
|
352
|
-
const parent = dirname(cwd);
|
|
353
|
-
if (parent === cwd) {
|
|
354
|
-
return {
|
|
355
|
-
name: t("workspace:checks.parentDir"),
|
|
356
|
-
status: "info",
|
|
357
|
-
message: t("workspace:status.rootDir")
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
try {
|
|
361
|
-
const stat = statSync(parent);
|
|
362
|
-
if (!stat.isDirectory()) {
|
|
363
|
-
return {
|
|
364
|
-
name: t("workspace:checks.parentDir"),
|
|
365
|
-
status: "fail",
|
|
366
|
-
message: t("workspace:status.parentNotDir")
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
const { readdirSync } = await import('node:fs');
|
|
370
|
-
readdirSync(parent);
|
|
371
|
-
return {
|
|
372
|
-
name: t("workspace:checks.parentDir"),
|
|
373
|
-
status: "pass",
|
|
374
|
-
message: t("workspace:status.parentOk")
|
|
375
|
-
};
|
|
376
|
-
} catch (error) {
|
|
377
|
-
return {
|
|
378
|
-
name: t("workspace:checks.parentDir"),
|
|
379
|
-
status: "warn",
|
|
380
|
-
message: t("workspace:status.parentAccessIssue"),
|
|
381
|
-
details: error instanceof Error ? error.message : String(error)
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
async function checkEnvironment() {
|
|
386
|
-
const isWSL = existsSync("/proc/version") && readFileSync("/proc/version", "utf-8").toLowerCase().includes("microsoft");
|
|
387
|
-
const isDocker = existsSync("/.dockerenv") || existsSync("/proc/1/cgroup") && readFileSync("/proc/1/cgroup", "utf-8").includes("docker");
|
|
388
|
-
if (isWSL) {
|
|
389
|
-
return {
|
|
390
|
-
name: t("workspace:checks.environment"),
|
|
391
|
-
status: "info",
|
|
392
|
-
message: t("workspace:status.wslDetected"),
|
|
393
|
-
details: t("workspace:details.wslTips")
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
if (isDocker) {
|
|
397
|
-
return {
|
|
398
|
-
name: t("workspace:checks.environment"),
|
|
399
|
-
status: "info",
|
|
400
|
-
message: t("workspace:status.dockerDetected"),
|
|
401
|
-
details: t("workspace:details.dockerTips")
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
return {
|
|
405
|
-
name: t("workspace:checks.environment"),
|
|
406
|
-
status: "pass",
|
|
407
|
-
message: t("workspace:status.nativeEnv")
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
async function runWorkspaceCheck(targetDir) {
|
|
411
|
-
const cwd = targetDir ? resolve(targetDir) : process__default.cwd();
|
|
412
|
-
const spinner = ora(t("workspace:checking")).start();
|
|
413
|
-
const checks = [];
|
|
414
|
-
spinner.text = t("workspace:checkingCwd");
|
|
415
|
-
checks.push(await checkWorkingDirectory(cwd));
|
|
416
|
-
spinner.text = t("workspace:checkingWrite");
|
|
417
|
-
checks.push(await checkWritePermission(cwd));
|
|
418
|
-
spinner.text = t("workspace:checkingOwnership");
|
|
419
|
-
checks.push(await checkDirectoryOwnership(cwd));
|
|
420
|
-
spinner.text = t("workspace:checkingTrusted");
|
|
421
|
-
checks.push(await checkTrustedDirectories(cwd));
|
|
422
|
-
spinner.text = t("workspace:checkingPath");
|
|
423
|
-
checks.push(await checkPathCharacters(cwd));
|
|
424
|
-
spinner.text = t("workspace:checkingHome");
|
|
425
|
-
checks.push(await checkHomeDirectory(cwd));
|
|
426
|
-
spinner.text = t("workspace:checkingDisk");
|
|
427
|
-
checks.push(await checkDiskSpace(cwd));
|
|
428
|
-
spinner.text = t("workspace:checkingParent");
|
|
429
|
-
checks.push(await checkParentDirectory(cwd));
|
|
430
|
-
spinner.text = t("workspace:checkingEnv");
|
|
431
|
-
checks.push(await checkEnvironment());
|
|
432
|
-
spinner.stop();
|
|
433
|
-
const recommendations = [];
|
|
434
|
-
const hasFailures = checks.some((c) => c.status === "fail");
|
|
435
|
-
const hasWarnings = checks.some((c) => c.status === "warn");
|
|
436
|
-
if (hasFailures) {
|
|
437
|
-
recommendations.push(t("workspace:recommendations.fixFailures"));
|
|
438
|
-
}
|
|
439
|
-
if (hasWarnings) {
|
|
440
|
-
recommendations.push(t("workspace:recommendations.reviewWarnings"));
|
|
441
|
-
}
|
|
442
|
-
const trustedCheck = checks.find((c) => c.name === t("workspace:checks.trustedDirs"));
|
|
443
|
-
if (trustedCheck && trustedCheck.status !== "pass") {
|
|
444
|
-
recommendations.push(t("workspace:recommendations.trustDir", { cmd: `claude config add trustedDirectories "${cwd}"` }));
|
|
445
|
-
}
|
|
446
|
-
return {
|
|
447
|
-
cwd,
|
|
448
|
-
isValid: !hasFailures,
|
|
449
|
-
checks,
|
|
450
|
-
recommendations
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
function displayWorkspaceReport(report) {
|
|
454
|
-
console.log(a.green(`
|
|
455
|
-
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 ${t("workspace:title")} \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
456
|
-
`));
|
|
457
|
-
console.log(a.white.bold(`${t("workspace:currentDir")}: ${a.yellow(report.cwd)}
|
|
458
|
-
`));
|
|
459
|
-
for (const check of report.checks) {
|
|
460
|
-
let icon;
|
|
461
|
-
let color;
|
|
462
|
-
switch (check.status) {
|
|
463
|
-
case "pass":
|
|
464
|
-
icon = "\u2705";
|
|
465
|
-
color = a.green;
|
|
466
|
-
break;
|
|
467
|
-
case "warn":
|
|
468
|
-
icon = "\u26A0\uFE0F";
|
|
469
|
-
color = a.yellow;
|
|
470
|
-
break;
|
|
471
|
-
case "fail":
|
|
472
|
-
icon = "\u274C";
|
|
473
|
-
color = a.red;
|
|
474
|
-
break;
|
|
475
|
-
case "info":
|
|
476
|
-
default:
|
|
477
|
-
icon = "\u2139\uFE0F";
|
|
478
|
-
color = a.gray;
|
|
479
|
-
break;
|
|
480
|
-
}
|
|
481
|
-
console.log(`${icon} ${a.bold(check.name.padEnd(20))} ${color(check.message)}`);
|
|
482
|
-
if (check.details) {
|
|
483
|
-
console.log(a.gray(` ${check.details}`));
|
|
484
|
-
}
|
|
485
|
-
if (check.fixDescription && (check.status === "fail" || check.status === "warn")) {
|
|
486
|
-
console.log(a.dim(` \u{1F4A1} ${check.fixDescription}`));
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
console.log("");
|
|
490
|
-
console.log(a.dim("\u2500".repeat(50)));
|
|
491
|
-
if (report.isValid) {
|
|
492
|
-
console.log(STATUS.success(t("workspace:summary.valid")));
|
|
493
|
-
} else {
|
|
494
|
-
console.log(STATUS.error(t("workspace:summary.invalid")));
|
|
495
|
-
}
|
|
496
|
-
if (report.recommendations.length > 0) {
|
|
497
|
-
console.log(a.yellow(`
|
|
498
|
-
${t("workspace:recommendations.title")}:`));
|
|
499
|
-
for (const rec of report.recommendations) {
|
|
500
|
-
console.log(a.yellow(` \u2022 ${rec}`));
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
console.log("");
|
|
504
|
-
}
|
|
505
|
-
async function runWorkspaceWizard(targetDir) {
|
|
506
|
-
const report = await runWorkspaceCheck(targetDir);
|
|
507
|
-
displayWorkspaceReport(report);
|
|
508
|
-
const fixableChecks = report.checks.filter(
|
|
509
|
-
(c) => c.fix && (c.status === "fail" || c.status === "warn")
|
|
510
|
-
);
|
|
511
|
-
if (fixableChecks.length === 0) {
|
|
512
|
-
if (report.isValid) {
|
|
513
|
-
console.log(STATUS.success(t("workspace:wizard.allGood")));
|
|
514
|
-
} else {
|
|
515
|
-
console.log(STATUS.warning(t("workspace:wizard.manualFix")));
|
|
516
|
-
}
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
console.log("");
|
|
520
|
-
console.log(a.green(t("workspace:wizard.autoFixing", { count: fixableChecks.length })));
|
|
521
|
-
for (const check of fixableChecks) {
|
|
522
|
-
const spinner = ora(`${t("workspace:wizard.fixing")} ${check.name}...`).start();
|
|
523
|
-
try {
|
|
524
|
-
const success = await check.fix();
|
|
525
|
-
if (success) {
|
|
526
|
-
spinner.succeed(`${check.name} ${t("workspace:wizard.fixed")}`);
|
|
527
|
-
} else {
|
|
528
|
-
spinner.fail(`${check.name} ${t("workspace:wizard.fixFailed")}`);
|
|
529
|
-
}
|
|
530
|
-
} catch (error) {
|
|
531
|
-
spinner.fail(`${check.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
console.log("");
|
|
535
|
-
console.log(a.green(t("workspace:wizard.verifying")));
|
|
536
|
-
const newReport = await runWorkspaceCheck(targetDir);
|
|
537
|
-
if (newReport.isValid) {
|
|
538
|
-
console.log(STATUS.success(t("workspace:wizard.allFixed")));
|
|
539
|
-
} else {
|
|
540
|
-
console.log(STATUS.warning(t("workspace:wizard.someRemain")));
|
|
541
|
-
displayWorkspaceReport(newReport);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
async function checkClaudeCode() {
|
|
546
|
-
const hasCommand = await commandExists("claude");
|
|
547
|
-
if (hasCommand) {
|
|
548
|
-
return { name: "Claude Code", status: "ok", message: "Installed" };
|
|
549
|
-
}
|
|
550
|
-
return {
|
|
551
|
-
name: "Claude Code",
|
|
552
|
-
status: "error",
|
|
553
|
-
message: "Not installed",
|
|
554
|
-
fix: "Run: npm install -g @anthropic-ai/claude-code"
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
async function checkClaudeDir() {
|
|
558
|
-
if (existsSync(CLAUDE_DIR)) {
|
|
559
|
-
return { name: "Config Directory", status: "ok", message: CLAUDE_DIR };
|
|
560
|
-
}
|
|
561
|
-
return {
|
|
562
|
-
name: "Config Directory",
|
|
563
|
-
status: "error",
|
|
564
|
-
message: "Does not exist",
|
|
565
|
-
fix: "Run: npx ccjk init"
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
async function checkSettings() {
|
|
569
|
-
if (!existsSync(SETTINGS_FILE)) {
|
|
570
|
-
return {
|
|
571
|
-
name: "settings.json",
|
|
572
|
-
status: "warning",
|
|
573
|
-
message: "Not found",
|
|
574
|
-
fix: "Run: npx ccjk init"
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
try {
|
|
578
|
-
const { readFileSync } = await import('node:fs');
|
|
579
|
-
const content = readFileSync(SETTINGS_FILE, "utf-8");
|
|
580
|
-
const settings = JSON.parse(content);
|
|
581
|
-
const issues = [];
|
|
582
|
-
if (settings.$schema && settings.$schema !== "https://json.schemastore.org/claude-code-settings.json") {
|
|
583
|
-
issues.push("Invalid $schema URL");
|
|
584
|
-
}
|
|
585
|
-
if (typeof settings.attribution === "string") {
|
|
586
|
-
issues.push("attribution should be an object, not a string");
|
|
587
|
-
}
|
|
588
|
-
if (settings.fileSuggestion && settings.fileSuggestion.type !== "command") {
|
|
589
|
-
issues.push('fileSuggestion.type must be "command"');
|
|
590
|
-
}
|
|
591
|
-
if (settings.permissions?.allow) {
|
|
592
|
-
const lowerCaseTools = settings.permissions.allow.filter(
|
|
593
|
-
(t) => /^[a-z]/.test(t) && !t.startsWith("Allow")
|
|
594
|
-
);
|
|
595
|
-
if (lowerCaseTools.length > 0) {
|
|
596
|
-
issues.push(`${lowerCaseTools.length} permission(s) with lowercase names`);
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
if (settings.plansDirectory === null) {
|
|
600
|
-
issues.push("plansDirectory should not be null");
|
|
601
|
-
}
|
|
602
|
-
if (issues.length > 0) {
|
|
603
|
-
return {
|
|
604
|
-
name: "settings.json",
|
|
605
|
-
status: "error",
|
|
606
|
-
message: `Validation issues: ${issues.length} problem(s)`,
|
|
607
|
-
fix: "Run: npx ccjk doctor --fix-settings",
|
|
608
|
-
details: issues
|
|
609
|
-
};
|
|
610
|
-
}
|
|
611
|
-
return { name: "settings.json", status: "ok", message: "Valid configuration" };
|
|
612
|
-
} catch (_error) {
|
|
613
|
-
return {
|
|
614
|
-
name: "settings.json",
|
|
615
|
-
status: "error",
|
|
616
|
-
message: "Invalid JSON",
|
|
617
|
-
fix: "Run: npx ccjk init"
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
async function checkWorkflows() {
|
|
622
|
-
const commandsDir = join(CLAUDE_DIR, "commands");
|
|
623
|
-
if (existsSync(commandsDir)) {
|
|
624
|
-
try {
|
|
625
|
-
const files = readdirSync(commandsDir, { recursive: true });
|
|
626
|
-
const mdFiles = files.filter((f) => String(f).endsWith(".md"));
|
|
627
|
-
return {
|
|
628
|
-
name: "Workflows",
|
|
629
|
-
status: "ok",
|
|
630
|
-
message: `${mdFiles.length} commands installed`
|
|
631
|
-
};
|
|
632
|
-
} catch {
|
|
633
|
-
return { name: "Workflows", status: "warning", message: "Cannot read directory" };
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
return {
|
|
637
|
-
name: "Workflows",
|
|
638
|
-
status: "warning",
|
|
639
|
-
message: "Not installed",
|
|
640
|
-
fix: "Run: npx ccjk update"
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
async function checkMcp() {
|
|
644
|
-
const mcpConfigPath = join(CLAUDE_DIR, "mcp.json");
|
|
645
|
-
const settingsPath = SETTINGS_FILE;
|
|
646
|
-
if (existsSync(settingsPath)) {
|
|
647
|
-
try {
|
|
648
|
-
const { readFileSync } = await import('node:fs');
|
|
649
|
-
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
650
|
-
if (settings.mcpServers && Object.keys(settings.mcpServers).length > 0) {
|
|
651
|
-
const count = Object.keys(settings.mcpServers).length;
|
|
652
|
-
return { name: "MCP Services", status: "ok", message: `${count} services configured` };
|
|
653
|
-
}
|
|
654
|
-
} catch {
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
if (existsSync(mcpConfigPath)) {
|
|
658
|
-
return { name: "MCP Services", status: "ok", message: "Configured" };
|
|
659
|
-
}
|
|
660
|
-
return {
|
|
661
|
-
name: "MCP Services",
|
|
662
|
-
status: "warning",
|
|
663
|
-
message: "Not configured",
|
|
664
|
-
fix: "Run: npx ccjk init and select MCP services"
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
async function checkCcr() {
|
|
668
|
-
const hasCcr = await commandExists("ccr");
|
|
669
|
-
if (hasCcr) {
|
|
670
|
-
return { name: "CCR Proxy", status: "ok", message: "Installed" };
|
|
671
|
-
}
|
|
672
|
-
return {
|
|
673
|
-
name: "CCR Proxy",
|
|
674
|
-
status: "warning",
|
|
675
|
-
message: "Not installed (optional)",
|
|
676
|
-
fix: "Run: npx ccjk ccr to install"
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
async function checkOutputStyles() {
|
|
680
|
-
const stylesDir = join(CLAUDE_DIR, "output-styles");
|
|
681
|
-
if (existsSync(stylesDir)) {
|
|
682
|
-
try {
|
|
683
|
-
const files = readdirSync(stylesDir).filter((f) => f.endsWith(".md"));
|
|
684
|
-
return {
|
|
685
|
-
name: "Output Styles",
|
|
686
|
-
status: "ok",
|
|
687
|
-
message: `${files.length} styles available`
|
|
688
|
-
};
|
|
689
|
-
} catch {
|
|
690
|
-
return { name: "Output Styles", status: "warning", message: "Cannot read directory" };
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
return {
|
|
694
|
-
name: "Output Styles",
|
|
695
|
-
status: "warning",
|
|
696
|
-
message: "Not installed",
|
|
697
|
-
fix: "Run: npx ccjk init"
|
|
698
|
-
};
|
|
699
|
-
}
|
|
700
|
-
async function checkProviders(codeType = "claude-code") {
|
|
701
|
-
try {
|
|
702
|
-
const providers = await getApiProviderPresets(codeType);
|
|
703
|
-
if (providers.length === 0) {
|
|
704
|
-
return {
|
|
705
|
-
name: "API Providers",
|
|
706
|
-
status: "warning",
|
|
707
|
-
message: "No providers available"
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
|
-
const monitor = new ProviderHealthMonitor({
|
|
711
|
-
timeout: 3e3,
|
|
712
|
-
degradedLatencyThreshold: 1e3,
|
|
713
|
-
unhealthyLatencyThreshold: 3e3
|
|
714
|
-
});
|
|
715
|
-
monitor.setProviders(providers);
|
|
716
|
-
const results = await Promise.race([
|
|
717
|
-
Promise.all(
|
|
718
|
-
providers.map(async (provider) => {
|
|
719
|
-
const result = await monitor.checkHealth(provider);
|
|
720
|
-
return { provider, result };
|
|
721
|
-
})
|
|
722
|
-
),
|
|
723
|
-
new Promise((resolve2) => {
|
|
724
|
-
setTimeout(() => resolve2(null), 5e3);
|
|
725
|
-
})
|
|
726
|
-
]);
|
|
727
|
-
if (!results) {
|
|
728
|
-
return {
|
|
729
|
-
name: "API Providers",
|
|
730
|
-
status: "warning",
|
|
731
|
-
message: "Health check timeout"
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
const healthyCount = results.filter((r) => r.result.success).length;
|
|
735
|
-
if (healthyCount === 0) {
|
|
736
|
-
return {
|
|
737
|
-
name: "API Providers",
|
|
738
|
-
status: "error",
|
|
739
|
-
message: "All providers unavailable",
|
|
740
|
-
fix: "Check your network connection"
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
if (healthyCount < providers.length) {
|
|
744
|
-
return {
|
|
745
|
-
name: "API Providers",
|
|
746
|
-
status: "warning",
|
|
747
|
-
message: `${healthyCount}/${providers.length} providers healthy`
|
|
748
|
-
};
|
|
749
|
-
}
|
|
750
|
-
return {
|
|
751
|
-
name: "API Providers",
|
|
752
|
-
status: "ok",
|
|
753
|
-
message: `${healthyCount} providers healthy`
|
|
754
|
-
};
|
|
755
|
-
} catch {
|
|
756
|
-
return {
|
|
757
|
-
name: "API Providers",
|
|
758
|
-
status: "warning",
|
|
759
|
-
message: "Health check failed"
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
async function checkPermissionRules() {
|
|
764
|
-
const isZh = i18n.language === "zh-CN";
|
|
765
|
-
try {
|
|
766
|
-
const permissionManager = getPermissionManager();
|
|
767
|
-
const unreachableRules = permissionManager.getUnreachableRules();
|
|
768
|
-
const allDiagnostics = permissionManager.getAllDiagnostics();
|
|
769
|
-
const shadowedRules = allDiagnostics.filter((d) => d.shadowedBy.length > 0);
|
|
770
|
-
const conflictedRules = allDiagnostics.filter((d) => d.conflicts.length > 0);
|
|
771
|
-
const problemCount = unreachableRules.length + shadowedRules.length + conflictedRules.length;
|
|
772
|
-
if (problemCount === 0) {
|
|
773
|
-
const stats = permissionManager.getStats();
|
|
774
|
-
return {
|
|
775
|
-
name: "Permission Rules",
|
|
776
|
-
status: "ok",
|
|
777
|
-
message: `${stats.total} rules configured`
|
|
778
|
-
};
|
|
779
|
-
}
|
|
780
|
-
const details = [];
|
|
781
|
-
if (unreachableRules.length > 0) {
|
|
782
|
-
details.push(isZh ? `${unreachableRules.length} unreachable rule(s)` : `${unreachableRules.length} unreachable rule(s)`);
|
|
783
|
-
for (const rule of unreachableRules.slice(0, 3)) {
|
|
784
|
-
details.push(` - ${a.dim(rule.pattern)}`);
|
|
785
|
-
}
|
|
786
|
-
if (unreachableRules.length > 3) {
|
|
787
|
-
details.push(` ... ${isZh ? "and" : "and"} ${unreachableRules.length - 3} ${isZh ? "more" : "more"}`);
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
if (shadowedRules.length > 0) {
|
|
791
|
-
details.push(isZh ? `${shadowedRules.length} shadowed rule(s)` : `${shadowedRules.length} shadowed rule(s)`);
|
|
792
|
-
for (const diag of shadowedRules.slice(0, 2)) {
|
|
793
|
-
details.push(` - ${a.dim(diag.rule.pattern)} ${a.dim(isZh ? "shadowed by" : "shadowed by")} ${diag.shadowedBy[0].pattern}`);
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
if (conflictedRules.length > 0) {
|
|
797
|
-
details.push(isZh ? `${conflictedRules.length} conflicted rule(s)` : `${conflictedRules.length} conflicted rule(s)`);
|
|
798
|
-
}
|
|
799
|
-
return {
|
|
800
|
-
name: "Permission Rules",
|
|
801
|
-
status: "warning",
|
|
802
|
-
message: `${problemCount} ${isZh ? "problematic" : "problematic"} ${isZh ? "rule(s)" : "rule(s)"}`,
|
|
803
|
-
fix: isZh ? "Run: ccjk permissions diagnose" : "Run: ccjk permissions diagnose",
|
|
804
|
-
details
|
|
805
|
-
};
|
|
806
|
-
} catch {
|
|
807
|
-
return {
|
|
808
|
-
name: "Permission Rules",
|
|
809
|
-
status: "warning",
|
|
810
|
-
message: "Unable to check"
|
|
811
|
-
};
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
async function fixSettingsFile() {
|
|
815
|
-
const isZh = i18n.language === "zh-CN";
|
|
816
|
-
const { copyConfigFiles } = await import('./config.mjs').then(function (n) { return n.j; });
|
|
817
|
-
console.log("");
|
|
818
|
-
console.log(a.bold.cyan("\u{1F527} Fixing settings.json"));
|
|
819
|
-
console.log(a.dim("\u2500".repeat(50)));
|
|
820
|
-
console.log("");
|
|
821
|
-
const backupPath = join(CLAUDE_DIR, "backup", `settings.backup.${Date.now()}.json`);
|
|
822
|
-
try {
|
|
823
|
-
if (existsSync(SETTINGS_FILE)) {
|
|
824
|
-
mkdirSync(join(CLAUDE_DIR, "backup"), { recursive: true });
|
|
825
|
-
copyFileSync(SETTINGS_FILE, backupPath);
|
|
826
|
-
console.log(a.green(`\u2714 ${isZh ? "\u5DF2\u5907\u4EFD\u65E7\u8BBE\u7F6E" : "Backed up settings"}: ${backupPath}`));
|
|
827
|
-
}
|
|
828
|
-
} catch (_error) {
|
|
829
|
-
console.log(a.yellow(`\u26A0\uFE0F ${isZh ? "\u5907\u4EFD\u5931\u8D25\uFF0C\u7EE7\u7EED..." : "Backup failed, continuing..."}`));
|
|
830
|
-
}
|
|
831
|
-
console.log("");
|
|
832
|
-
console.log(a.dim(isZh ? "\u6B63\u5728\u5408\u5E76\u6A21\u677F\u8BBE\u7F6E..." : "Merging template settings..."));
|
|
833
|
-
copyConfigFiles(false);
|
|
834
|
-
const checkResult = await checkSettings();
|
|
835
|
-
console.log("");
|
|
836
|
-
if (checkResult.status === "ok") {
|
|
837
|
-
console.log(a.green(`\u2705 ${isZh ? "\u8BBE\u7F6E\u5DF2\u4FEE\u590D\uFF01" : "Settings fixed successfully!"}`));
|
|
838
|
-
} else {
|
|
839
|
-
console.log(a.yellow(`\u26A0\uFE0F ${isZh ? "\u4ECD\u6709\u4E00\u4E9B\u95EE\u9898" : "Some issues remain"}:`));
|
|
840
|
-
if (checkResult.details) {
|
|
841
|
-
for (const detail of checkResult.details) {
|
|
842
|
-
console.log(a.dim(` \u2022 ${detail}`));
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
console.log("");
|
|
847
|
-
console.log(a.dim(isZh ? "\u63D0\u793A: \u8BF7\u91CD\u542F Claude Code \u4EE5\u5E94\u7528\u66F4\u6539" : "Tip: Restart Claude Code to apply changes"));
|
|
848
|
-
console.log("");
|
|
849
|
-
}
|
|
850
|
-
async function doctor(options = {}) {
|
|
851
|
-
const isZh = i18n.language === "zh-CN";
|
|
852
|
-
if (options.fixSettings) {
|
|
853
|
-
await fixSettingsFile();
|
|
854
|
-
return;
|
|
855
|
-
}
|
|
856
|
-
const checks = [
|
|
857
|
-
checkClaudeCode,
|
|
858
|
-
checkClaudeDir,
|
|
859
|
-
checkSettings,
|
|
860
|
-
checkWorkflows,
|
|
861
|
-
checkMcp,
|
|
862
|
-
checkPermissionRules,
|
|
863
|
-
checkCcr,
|
|
864
|
-
checkOutputStyles
|
|
865
|
-
];
|
|
866
|
-
if (options.checkProviders) {
|
|
867
|
-
checks.push(() => checkProviders(options.codeType));
|
|
868
|
-
}
|
|
869
|
-
const results = [];
|
|
870
|
-
for (const check of checks) {
|
|
871
|
-
const result = await check();
|
|
872
|
-
results.push(result);
|
|
873
|
-
}
|
|
874
|
-
if (options.json) {
|
|
875
|
-
const output = {
|
|
876
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
877
|
-
summary: {
|
|
878
|
-
total: results.length,
|
|
879
|
-
ok: results.filter((r) => r.status === "ok").length,
|
|
880
|
-
warning: results.filter((r) => r.status === "warning").length,
|
|
881
|
-
error: results.filter((r) => r.status === "error").length
|
|
882
|
-
},
|
|
883
|
-
checks: results.map((r) => ({
|
|
884
|
-
name: r.name,
|
|
885
|
-
status: r.status,
|
|
886
|
-
message: r.message,
|
|
887
|
-
fix: r.fix,
|
|
888
|
-
details: r.details
|
|
889
|
-
}))
|
|
890
|
-
};
|
|
891
|
-
console.log(JSON.stringify(output, null, 2));
|
|
892
|
-
return;
|
|
893
|
-
}
|
|
894
|
-
console.log("");
|
|
895
|
-
console.log(a.bold.cyan("\u{1F50D} CCJK Health Check"));
|
|
896
|
-
console.log(a.dim("\u2500".repeat(50)));
|
|
897
|
-
console.log("");
|
|
898
|
-
let hasErrors = false;
|
|
899
|
-
let hasWarnings = false;
|
|
900
|
-
for (const result of results) {
|
|
901
|
-
const statusIcon = result.status === "ok" ? a.green("\u2705") : result.status === "warning" ? a.yellow("\u26A0\uFE0F") : a.red("\u274C");
|
|
902
|
-
const statusColor = result.status === "ok" ? a.green : result.status === "warning" ? a.yellow : a.red;
|
|
903
|
-
console.log(`${statusIcon} ${a.bold(result.name)}: ${statusColor(result.message)}`);
|
|
904
|
-
if (result.fix) {
|
|
905
|
-
console.log(a.dim(` \u{1F4A1} Fix: ${result.fix}`));
|
|
906
|
-
}
|
|
907
|
-
if (result.details && result.details.length > 0) {
|
|
908
|
-
for (const detail of result.details) {
|
|
909
|
-
console.log(a.dim(` ${detail}`));
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
if (result.status === "error")
|
|
913
|
-
hasErrors = true;
|
|
914
|
-
if (result.status === "warning")
|
|
915
|
-
hasWarnings = true;
|
|
916
|
-
}
|
|
917
|
-
console.log("");
|
|
918
|
-
console.log(a.dim("\u2500".repeat(50)));
|
|
919
|
-
if (hasErrors) {
|
|
920
|
-
console.log(a.red("\u274C Issues found - please follow the suggestions above"));
|
|
921
|
-
} else if (hasWarnings) {
|
|
922
|
-
console.log(a.yellow("\u26A0\uFE0F Configuration is functional, but some features may be limited"));
|
|
923
|
-
} else {
|
|
924
|
-
console.log(a.green("\u2705 All checks passed - CCJK is properly configured!"));
|
|
925
|
-
}
|
|
926
|
-
console.log("");
|
|
927
|
-
if (!options.checkProviders) {
|
|
928
|
-
const { checkProvidersNow } = await inquirer.prompt({
|
|
929
|
-
type: "confirm",
|
|
930
|
-
name: "checkProvidersNow",
|
|
931
|
-
message: isZh ? "\u662F\u5426\u68C0\u67E5 API \u4F9B\u5E94\u5546\u5065\u5EB7\u72B6\u6001\uFF1F" : "Check API provider health status?",
|
|
932
|
-
default: false
|
|
933
|
-
});
|
|
934
|
-
if (checkProvidersNow) {
|
|
935
|
-
console.log("");
|
|
936
|
-
console.log(a.dim(isZh ? "\u6B63\u5728\u68C0\u67E5\u4F9B\u5E94\u5546..." : "Checking providers..."));
|
|
937
|
-
const providerResult = await checkProviders(options.codeType);
|
|
938
|
-
const statusIcon = providerResult.status === "ok" ? a.green("\u2705") : providerResult.status === "warning" ? a.yellow("\u26A0\uFE0F") : a.red("\u274C");
|
|
939
|
-
const statusColor = providerResult.status === "ok" ? a.green : providerResult.status === "warning" ? a.yellow : a.red;
|
|
940
|
-
console.log(`${statusIcon} ${a.bold(providerResult.name)}: ${statusColor(providerResult.message)}`);
|
|
941
|
-
if (providerResult.fix) {
|
|
942
|
-
console.log(a.dim(` \u{1F4A1} Fix: ${providerResult.fix}`));
|
|
943
|
-
}
|
|
944
|
-
console.log("");
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
const { runWorkspace } = await inquirer.prompt({
|
|
948
|
-
type: "confirm",
|
|
949
|
-
name: "runWorkspace",
|
|
950
|
-
message: isZh ? "\u662F\u5426\u68C0\u67E5\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u7684\u6587\u4EF6\u5199\u5165\u6743\u9650\uFF1F" : "Check file write permissions for current directory?",
|
|
951
|
-
default: false
|
|
952
|
-
});
|
|
953
|
-
if (runWorkspace) {
|
|
954
|
-
console.log("");
|
|
955
|
-
const report = await runWorkspaceCheck(process__default.cwd());
|
|
956
|
-
displayWorkspaceReport(report);
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
async function workspaceDiagnostics(targetDir) {
|
|
960
|
-
const dir = targetDir ? resolve(targetDir) : process__default.cwd();
|
|
961
|
-
await runWorkspaceWizard(dir);
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
export { doctor, workspaceDiagnostics };
|