aico-cli 2.0.36 → 2.0.38
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/simple-config.mjs +313 -83
- package/dist/cli.mjs +16 -15
- package/dist/index.d.mts +91 -41
- package/dist/index.d.ts +91 -41
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/templates/claude/CLAUDE.md +2 -0
- package/templates/claude/settings.json +98 -0
- package/templates/codebuddy/CODEBUDDY.md +2 -0
- package/templates/codebuddy/settings.json +128 -0
- package/templates/settings.json +7 -7
|
@@ -14,7 +14,7 @@ import { join, dirname, basename } from 'pathe';
|
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { EventEmitter } from 'node:events';
|
|
16
16
|
|
|
17
|
-
const version = "2.0.
|
|
17
|
+
const version = "2.0.38";
|
|
18
18
|
|
|
19
19
|
function displayBanner(subtitle) {
|
|
20
20
|
const defaultSubtitle = "\u4E00\u952E\u914D\u7F6E\u4F60\u7684\u5F00\u53D1\u73AF\u5883";
|
|
@@ -3217,6 +3217,34 @@ const CLAUDE_MD_FILE = join(CLAUDE_DIR, "CLAUDE.md");
|
|
|
3217
3217
|
const ClAUDE_CONFIG_FILE = join(homedir(), ".claude.json");
|
|
3218
3218
|
const LEGACY_AICO_CONFIG_FILE = join(homedir(), ".aico.json");
|
|
3219
3219
|
const AICO_CONFIG_FILE = join(CLAUDE_DIR, ".aico-config.json");
|
|
3220
|
+
const TARGET_CONFIGS = {
|
|
3221
|
+
claude: {
|
|
3222
|
+
dirName: ".claude",
|
|
3223
|
+
mainConfigFile: "CLAUDE.md",
|
|
3224
|
+
settingsFile: "settings.json"
|
|
3225
|
+
// 无需重命名
|
|
3226
|
+
},
|
|
3227
|
+
codebuddy: {
|
|
3228
|
+
dirName: ".codebuddy",
|
|
3229
|
+
mainConfigFile: "CODEBUDDY.md",
|
|
3230
|
+
settingsFile: "settings.json",
|
|
3231
|
+
fileRenames: {
|
|
3232
|
+
"CLAUDE.md": "CODEBUDDY.md"
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
};
|
|
3236
|
+
function getTargetDir(target = "claude") {
|
|
3237
|
+
return join(homedir(), TARGET_CONFIGS[target].dirName);
|
|
3238
|
+
}
|
|
3239
|
+
function getTargetSettingsFile(target = "claude") {
|
|
3240
|
+
return join(getTargetDir(target), TARGET_CONFIGS[target].settingsFile);
|
|
3241
|
+
}
|
|
3242
|
+
function getTargetMainConfigFile(target = "claude") {
|
|
3243
|
+
return join(getTargetDir(target), TARGET_CONFIGS[target].mainConfigFile);
|
|
3244
|
+
}
|
|
3245
|
+
function getTargetAicoConfigFile(target = "claude") {
|
|
3246
|
+
return join(getTargetDir(target), ".aico-config.json");
|
|
3247
|
+
}
|
|
3220
3248
|
const SUPPORTED_LANGS = ["zh-CN"];
|
|
3221
3249
|
const LANG_LABELS = {
|
|
3222
3250
|
"zh-CN": "\u7B80\u4F53\u4E2D\u6587"
|
|
@@ -3753,18 +3781,19 @@ function updateAicoConfig(updates) {
|
|
|
3753
3781
|
writeAicoConfig(newConfig);
|
|
3754
3782
|
}
|
|
3755
3783
|
|
|
3756
|
-
function getMcpConfigPath() {
|
|
3757
|
-
|
|
3784
|
+
function getMcpConfigPath(target = "claude") {
|
|
3785
|
+
const configFileName = target === "claude" ? ".claude.json" : `.${target}.json`;
|
|
3786
|
+
return join(homedir(), configFileName);
|
|
3758
3787
|
}
|
|
3759
|
-
function readMcpConfig() {
|
|
3760
|
-
return readJsonConfig(
|
|
3788
|
+
function readMcpConfig(target = "claude") {
|
|
3789
|
+
return readJsonConfig(getMcpConfigPath(target));
|
|
3761
3790
|
}
|
|
3762
|
-
function writeMcpConfig(config) {
|
|
3763
|
-
writeJsonConfig(
|
|
3791
|
+
function writeMcpConfig(config, target = "claude") {
|
|
3792
|
+
writeJsonConfig(getMcpConfigPath(target), config);
|
|
3764
3793
|
}
|
|
3765
|
-
function backupMcpConfig() {
|
|
3766
|
-
const backupBaseDir = join(
|
|
3767
|
-
return backupJsonConfig(
|
|
3794
|
+
function backupMcpConfig(target = "claude") {
|
|
3795
|
+
const backupBaseDir = join(getTargetDir(target), "backup");
|
|
3796
|
+
return backupJsonConfig(getMcpConfigPath(target), backupBaseDir);
|
|
3768
3797
|
}
|
|
3769
3798
|
function mergeMcpServers(existing, newServers) {
|
|
3770
3799
|
const config = existing || { mcpServers: {} };
|
|
@@ -3811,9 +3840,9 @@ function fixWindowsMcpConfig(config) {
|
|
|
3811
3840
|
}
|
|
3812
3841
|
return fixed;
|
|
3813
3842
|
}
|
|
3814
|
-
function updateClaudeConfigEnv(envVars) {
|
|
3843
|
+
function updateClaudeConfigEnv(envVars, target = "claude") {
|
|
3815
3844
|
try {
|
|
3816
|
-
let config = readMcpConfig();
|
|
3845
|
+
let config = readMcpConfig(target);
|
|
3817
3846
|
if (!config) {
|
|
3818
3847
|
config = { mcpServers: {} };
|
|
3819
3848
|
}
|
|
@@ -3821,15 +3850,15 @@ function updateClaudeConfigEnv(envVars) {
|
|
|
3821
3850
|
config.env = {};
|
|
3822
3851
|
}
|
|
3823
3852
|
Object.assign(config.env, envVars);
|
|
3824
|
-
writeMcpConfig(config);
|
|
3853
|
+
writeMcpConfig(config, target);
|
|
3825
3854
|
} catch (error) {
|
|
3826
|
-
console.error("Failed to update
|
|
3855
|
+
console.error("Failed to update config env", error);
|
|
3827
3856
|
throw error;
|
|
3828
3857
|
}
|
|
3829
3858
|
}
|
|
3830
|
-
function addCompletedOnboarding() {
|
|
3859
|
+
function addCompletedOnboarding(target = "claude") {
|
|
3831
3860
|
try {
|
|
3832
|
-
let config = readMcpConfig();
|
|
3861
|
+
let config = readMcpConfig(target);
|
|
3833
3862
|
if (!config) {
|
|
3834
3863
|
config = { mcpServers: {} };
|
|
3835
3864
|
}
|
|
@@ -3837,7 +3866,7 @@ function addCompletedOnboarding() {
|
|
|
3837
3866
|
return;
|
|
3838
3867
|
}
|
|
3839
3868
|
config.hasCompletedOnboarding = true;
|
|
3840
|
-
writeMcpConfig(config);
|
|
3869
|
+
writeMcpConfig(config, target);
|
|
3841
3870
|
} catch (error) {
|
|
3842
3871
|
readAicoConfig()?.preferredLang || "en";
|
|
3843
3872
|
console.error(messages.configuration?.failedToAddOnboardingFlag || "Failed to add onboarding flag", error);
|
|
@@ -4483,27 +4512,29 @@ function getPlatformStatusLineConfig() {
|
|
|
4483
4512
|
};
|
|
4484
4513
|
}
|
|
4485
4514
|
|
|
4486
|
-
function addCCometixLineConfig() {
|
|
4515
|
+
function addCCometixLineConfig(target = "claude") {
|
|
4487
4516
|
try {
|
|
4517
|
+
const settingsFile = getTargetSettingsFile(target);
|
|
4488
4518
|
const statusLineConfig = getPlatformStatusLineConfig();
|
|
4489
4519
|
let settings = {};
|
|
4490
|
-
if (exists(
|
|
4491
|
-
settings = readJsonConfig(
|
|
4520
|
+
if (exists(settingsFile)) {
|
|
4521
|
+
settings = readJsonConfig(settingsFile) || {};
|
|
4492
4522
|
}
|
|
4493
4523
|
settings.statusLine = statusLineConfig;
|
|
4494
|
-
writeJsonConfig(
|
|
4524
|
+
writeJsonConfig(settingsFile, settings);
|
|
4495
4525
|
return true;
|
|
4496
4526
|
} catch (error) {
|
|
4497
4527
|
console.error("Failed to add CCometixLine configuration:", error);
|
|
4498
4528
|
return false;
|
|
4499
4529
|
}
|
|
4500
4530
|
}
|
|
4501
|
-
function hasCCometixLineConfig() {
|
|
4531
|
+
function hasCCometixLineConfig(target = "claude") {
|
|
4502
4532
|
try {
|
|
4503
|
-
|
|
4533
|
+
const settingsFile = getTargetSettingsFile(target);
|
|
4534
|
+
if (!exists(settingsFile)) {
|
|
4504
4535
|
return false;
|
|
4505
4536
|
}
|
|
4506
|
-
const settings = readJsonConfig(
|
|
4537
|
+
const settings = readJsonConfig(settingsFile);
|
|
4507
4538
|
return !!settings?.statusLine?.command?.includes("ccline");
|
|
4508
4539
|
} catch (error) {
|
|
4509
4540
|
return false;
|
|
@@ -4513,6 +4544,12 @@ function hasCCometixLineConfig() {
|
|
|
4513
4544
|
const execAsync = promisify$1(exec$2);
|
|
4514
4545
|
class CCometixLineInstaller extends AbstractInstaller {
|
|
4515
4546
|
name = "CCometixLine";
|
|
4547
|
+
/**
|
|
4548
|
+
* 获取当前安装目标
|
|
4549
|
+
*/
|
|
4550
|
+
getTarget() {
|
|
4551
|
+
return this.context.target ?? "claude";
|
|
4552
|
+
}
|
|
4516
4553
|
async checkStatus() {
|
|
4517
4554
|
try {
|
|
4518
4555
|
await execAsync(COMETIX_COMMANDS.CHECK_INSTALL);
|
|
@@ -4542,10 +4579,11 @@ class CCometixLineInstaller extends AbstractInstaller {
|
|
|
4542
4579
|
}
|
|
4543
4580
|
async configure(options = {}) {
|
|
4544
4581
|
try {
|
|
4545
|
-
|
|
4582
|
+
const target = this.getTarget();
|
|
4583
|
+
if (hasCCometixLineConfig(target)) {
|
|
4546
4584
|
return this.createSkipResult("\u72B6\u6001\u680F\u914D\u7F6E\u5DF2\u5B58\u5728", "already_configured");
|
|
4547
4585
|
}
|
|
4548
|
-
addCCometixLineConfig();
|
|
4586
|
+
addCCometixLineConfig(target);
|
|
4549
4587
|
return this.createSuccessResult("\u72B6\u6001\u680F\u914D\u7F6E\u5B8C\u6210");
|
|
4550
4588
|
} catch (error) {
|
|
4551
4589
|
return this.handleError(error, "\u72B6\u6001\u680F\u914D\u7F6E");
|
|
@@ -4583,20 +4621,21 @@ function mergeAndCleanPermissions(templatePermissions, userPermissions) {
|
|
|
4583
4621
|
return cleanupPermissions(template, user);
|
|
4584
4622
|
}
|
|
4585
4623
|
|
|
4586
|
-
function ensureClaudeDir() {
|
|
4587
|
-
ensureDir(
|
|
4624
|
+
function ensureClaudeDir(target = "claude") {
|
|
4625
|
+
ensureDir(getTargetDir(target));
|
|
4588
4626
|
}
|
|
4589
|
-
function backupExistingConfig() {
|
|
4590
|
-
|
|
4627
|
+
function backupExistingConfig(target = "claude") {
|
|
4628
|
+
const targetDir = getTargetDir(target);
|
|
4629
|
+
if (!exists(targetDir)) {
|
|
4591
4630
|
return null;
|
|
4592
4631
|
}
|
|
4593
|
-
const backupBaseDir = join(
|
|
4632
|
+
const backupBaseDir = join(targetDir, "backup");
|
|
4594
4633
|
const backupDir = join(backupBaseDir, "latest");
|
|
4595
4634
|
ensureDir(backupDir);
|
|
4596
4635
|
const filter = (path) => {
|
|
4597
4636
|
return !path.includes("/backup");
|
|
4598
4637
|
};
|
|
4599
|
-
copyDir(
|
|
4638
|
+
copyDir(targetDir, backupDir, { filter });
|
|
4600
4639
|
return backupDir;
|
|
4601
4640
|
}
|
|
4602
4641
|
function copyConfigFiles(lang, onlyMd = false) {
|
|
@@ -4664,7 +4703,7 @@ const DEFAULT_FILE_COPY_CONFIGS = [
|
|
|
4664
4703
|
destination: join(CLAUDE_DIR, "personality.md"),
|
|
4665
4704
|
type: "file",
|
|
4666
4705
|
options: {
|
|
4667
|
-
mergeStrategy: "
|
|
4706
|
+
mergeStrategy: "copy",
|
|
4668
4707
|
backupBeforeCopy: true,
|
|
4669
4708
|
deleteBeforeCopy: true
|
|
4670
4709
|
}
|
|
@@ -4674,7 +4713,7 @@ const DEFAULT_FILE_COPY_CONFIGS = [
|
|
|
4674
4713
|
destination: join(CLAUDE_DIR, "language.md"),
|
|
4675
4714
|
type: "file",
|
|
4676
4715
|
options: {
|
|
4677
|
-
mergeStrategy: "
|
|
4716
|
+
mergeStrategy: "copy",
|
|
4678
4717
|
backupBeforeCopy: true,
|
|
4679
4718
|
deleteBeforeCopy: true
|
|
4680
4719
|
}
|
|
@@ -4684,7 +4723,7 @@ const DEFAULT_FILE_COPY_CONFIGS = [
|
|
|
4684
4723
|
destination: join(CLAUDE_DIR, "CLAUDE.md"),
|
|
4685
4724
|
type: "file",
|
|
4686
4725
|
options: {
|
|
4687
|
-
mergeStrategy: "
|
|
4726
|
+
mergeStrategy: "copy",
|
|
4688
4727
|
backupBeforeCopy: true,
|
|
4689
4728
|
deleteBeforeCopy: true
|
|
4690
4729
|
}
|
|
@@ -4694,16 +4733,106 @@ const DEFAULT_FILE_COPY_CONFIGS = [
|
|
|
4694
4733
|
destination: join(CLAUDE_DIR, "settings.json"),
|
|
4695
4734
|
type: "file",
|
|
4696
4735
|
options: {
|
|
4697
|
-
mergeStrategy: "
|
|
4736
|
+
mergeStrategy: "copy",
|
|
4698
4737
|
backupBeforeCopy: true,
|
|
4699
4738
|
deleteBeforeCopy: true
|
|
4700
4739
|
}
|
|
4701
4740
|
}
|
|
4702
4741
|
];
|
|
4703
|
-
function
|
|
4742
|
+
function getFileCopyConfigsForTarget(target = "claude") {
|
|
4743
|
+
const targetDir = getTargetDir(target);
|
|
4744
|
+
const targetConfig = TARGET_CONFIGS[target];
|
|
4745
|
+
const templateSubDir = target;
|
|
4746
|
+
return [
|
|
4747
|
+
{
|
|
4748
|
+
source: "templates/agents",
|
|
4749
|
+
destination: join(targetDir, "agents"),
|
|
4750
|
+
type: "directory",
|
|
4751
|
+
options: {
|
|
4752
|
+
mergeStrategy: "copy",
|
|
4753
|
+
backupBeforeCopy: true,
|
|
4754
|
+
deleteBeforeCopy: true
|
|
4755
|
+
}
|
|
4756
|
+
},
|
|
4757
|
+
{
|
|
4758
|
+
source: "templates/hooks",
|
|
4759
|
+
destination: join(targetDir, "hooks"),
|
|
4760
|
+
type: "directory",
|
|
4761
|
+
options: {
|
|
4762
|
+
mergeStrategy: "copy",
|
|
4763
|
+
backupBeforeCopy: true,
|
|
4764
|
+
deleteBeforeCopy: true
|
|
4765
|
+
}
|
|
4766
|
+
},
|
|
4767
|
+
{
|
|
4768
|
+
source: "templates/commands",
|
|
4769
|
+
destination: join(targetDir, "commands"),
|
|
4770
|
+
type: "directory",
|
|
4771
|
+
options: {
|
|
4772
|
+
mergeStrategy: "copy",
|
|
4773
|
+
backupBeforeCopy: true,
|
|
4774
|
+
deleteBeforeCopy: true
|
|
4775
|
+
}
|
|
4776
|
+
},
|
|
4777
|
+
{
|
|
4778
|
+
source: "templates/skills",
|
|
4779
|
+
destination: join(targetDir, "skills"),
|
|
4780
|
+
type: "directory",
|
|
4781
|
+
options: {
|
|
4782
|
+
mergeStrategy: "copy",
|
|
4783
|
+
backupBeforeCopy: true,
|
|
4784
|
+
deleteBeforeCopy: true
|
|
4785
|
+
}
|
|
4786
|
+
},
|
|
4787
|
+
{
|
|
4788
|
+
source: "templates/personality.md",
|
|
4789
|
+
destination: join(targetDir, "personality.md"),
|
|
4790
|
+
type: "file",
|
|
4791
|
+
options: {
|
|
4792
|
+
mergeStrategy: "copy",
|
|
4793
|
+
backupBeforeCopy: true,
|
|
4794
|
+
deleteBeforeCopy: true
|
|
4795
|
+
}
|
|
4796
|
+
},
|
|
4797
|
+
{
|
|
4798
|
+
source: "templates/language.md",
|
|
4799
|
+
destination: join(targetDir, "language.md"),
|
|
4800
|
+
type: "file",
|
|
4801
|
+
options: {
|
|
4802
|
+
mergeStrategy: "copy",
|
|
4803
|
+
backupBeforeCopy: true,
|
|
4804
|
+
deleteBeforeCopy: true
|
|
4805
|
+
}
|
|
4806
|
+
},
|
|
4807
|
+
// 使用目标特定的主配置文件 (CLAUDE.md 或 CODEBUDDY.md)
|
|
4808
|
+
{
|
|
4809
|
+
source: `templates/${templateSubDir}/${targetConfig.mainConfigFile}`,
|
|
4810
|
+
destination: join(targetDir, targetConfig.mainConfigFile),
|
|
4811
|
+
type: "file",
|
|
4812
|
+
options: {
|
|
4813
|
+
mergeStrategy: "copy",
|
|
4814
|
+
backupBeforeCopy: true,
|
|
4815
|
+
deleteBeforeCopy: true
|
|
4816
|
+
}
|
|
4817
|
+
},
|
|
4818
|
+
// 使用目标特定的 settings.json,直接替换而不是合并
|
|
4819
|
+
{
|
|
4820
|
+
source: `templates/${templateSubDir}/settings.json`,
|
|
4821
|
+
destination: join(targetDir, "settings.json"),
|
|
4822
|
+
type: "file",
|
|
4823
|
+
options: {
|
|
4824
|
+
mergeStrategy: "copy",
|
|
4825
|
+
backupBeforeCopy: true,
|
|
4826
|
+
deleteBeforeCopy: true
|
|
4827
|
+
}
|
|
4828
|
+
}
|
|
4829
|
+
];
|
|
4830
|
+
}
|
|
4831
|
+
function copyConfigFilesWithConfig(configs = DEFAULT_FILE_COPY_CONFIGS, target = "claude") {
|
|
4704
4832
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
4705
4833
|
const distDir = dirname(dirname(currentFilePath));
|
|
4706
4834
|
const rootDir = dirname(distDir);
|
|
4835
|
+
const targetDir = getTargetDir(target);
|
|
4707
4836
|
for (const config of configs) {
|
|
4708
4837
|
const sourcePath = join(rootDir, config.source);
|
|
4709
4838
|
const destPath = config.destination;
|
|
@@ -4717,16 +4846,16 @@ function copyConfigFilesWithConfig(configs = DEFAULT_FILE_COPY_CONFIGS) {
|
|
|
4717
4846
|
ensureDir(destPath);
|
|
4718
4847
|
continue;
|
|
4719
4848
|
}
|
|
4720
|
-
handleDirectoryCopy(sourcePath, destPath, config.options);
|
|
4849
|
+
handleDirectoryCopy(sourcePath, destPath, config.options, targetDir);
|
|
4721
4850
|
} else if (config.type === "file") {
|
|
4722
|
-
handleFileCopy(sourcePath, destPath, config.options);
|
|
4851
|
+
handleFileCopy(sourcePath, destPath, config.options, targetDir);
|
|
4723
4852
|
}
|
|
4724
4853
|
}
|
|
4725
4854
|
}
|
|
4726
|
-
function handleFileCopy(sourcePath, destPath, options) {
|
|
4855
|
+
function handleFileCopy(sourcePath, destPath, options, targetDir = CLAUDE_DIR) {
|
|
4727
4856
|
const destExists = exists(destPath);
|
|
4728
4857
|
if (options?.backupBeforeCopy && destExists) {
|
|
4729
|
-
const backupDir = join(
|
|
4858
|
+
const backupDir = join(targetDir, "backup", "latest");
|
|
4730
4859
|
ensureDir(backupDir);
|
|
4731
4860
|
const backupPath = join(backupDir, basename(destPath));
|
|
4732
4861
|
copyFile(destPath, backupPath);
|
|
@@ -4747,10 +4876,10 @@ function handleFileCopy(sourcePath, destPath, options) {
|
|
|
4747
4876
|
copyFile(sourcePath, destPath);
|
|
4748
4877
|
}
|
|
4749
4878
|
}
|
|
4750
|
-
function handleDirectoryCopy(sourcePath, destPath, options) {
|
|
4879
|
+
function handleDirectoryCopy(sourcePath, destPath, options, targetDir = CLAUDE_DIR) {
|
|
4751
4880
|
const destExists = exists(destPath);
|
|
4752
4881
|
if (options?.backupBeforeCopy && destExists) {
|
|
4753
|
-
const backupDir = join(
|
|
4882
|
+
const backupDir = join(targetDir, "backup", "latest");
|
|
4754
4883
|
ensureDir(backupDir);
|
|
4755
4884
|
const backupPath = join(backupDir, basename(destPath));
|
|
4756
4885
|
copyDir(destPath, backupPath, {
|
|
@@ -4803,10 +4932,11 @@ function getDefaultSettings() {
|
|
|
4803
4932
|
return {};
|
|
4804
4933
|
}
|
|
4805
4934
|
}
|
|
4806
|
-
function configureApi(apiConfig) {
|
|
4935
|
+
function configureApi(apiConfig, target = "claude") {
|
|
4807
4936
|
if (!apiConfig) return null;
|
|
4937
|
+
const settingsFile = getTargetSettingsFile(target);
|
|
4808
4938
|
let settings = getDefaultSettings();
|
|
4809
|
-
const existingSettings = readJsonConfig(
|
|
4939
|
+
const existingSettings = readJsonConfig(settingsFile);
|
|
4810
4940
|
if (existingSettings) {
|
|
4811
4941
|
settings = deepMerge(settings, existingSettings);
|
|
4812
4942
|
}
|
|
@@ -4820,9 +4950,9 @@ function configureApi(apiConfig) {
|
|
|
4820
4950
|
if (apiConfig.url) {
|
|
4821
4951
|
settings.env.ANTHROPIC_BASE_URL = apiConfig.url;
|
|
4822
4952
|
}
|
|
4823
|
-
writeJsonConfig(
|
|
4953
|
+
writeJsonConfig(settingsFile, settings);
|
|
4824
4954
|
try {
|
|
4825
|
-
addCompletedOnboarding();
|
|
4955
|
+
addCompletedOnboarding(target);
|
|
4826
4956
|
} catch (error) {
|
|
4827
4957
|
console.error("\u8BBE\u7F6E\u5165\u95E8\u6807\u5FD7\u5931\u8D25", error);
|
|
4828
4958
|
}
|
|
@@ -4873,6 +5003,12 @@ function mergeSettingsFile(templatePath, targetPath) {
|
|
|
4873
5003
|
existingSettings.permissions?.allow
|
|
4874
5004
|
);
|
|
4875
5005
|
}
|
|
5006
|
+
if (templateSettings.hooks) {
|
|
5007
|
+
mergedSettings.hooks = templateSettings.hooks;
|
|
5008
|
+
}
|
|
5009
|
+
if (templateSettings.statusLine) {
|
|
5010
|
+
mergedSettings.statusLine = templateSettings.statusLine;
|
|
5011
|
+
}
|
|
4876
5012
|
writeJsonConfig(targetPath, mergedSettings);
|
|
4877
5013
|
} catch (error) {
|
|
4878
5014
|
console.error("\u5408\u5E76\u8BBE\u7F6E\u5931\u8D25", error);
|
|
@@ -4913,35 +5049,67 @@ function applyAiLanguageDirective(aiOutputLang) {
|
|
|
4913
5049
|
|
|
4914
5050
|
class ConfigInstaller extends AbstractInstaller {
|
|
4915
5051
|
name = "Config";
|
|
4916
|
-
fileCopyConfigs =
|
|
5052
|
+
fileCopyConfigs = null;
|
|
5053
|
+
/**
|
|
5054
|
+
* 获取当前安装目标
|
|
5055
|
+
*/
|
|
5056
|
+
getTarget() {
|
|
5057
|
+
return this.context.target ?? "claude";
|
|
5058
|
+
}
|
|
5059
|
+
/**
|
|
5060
|
+
* 获取目标目录
|
|
5061
|
+
*/
|
|
5062
|
+
getTargetDirectory() {
|
|
5063
|
+
return getTargetDir(this.getTarget());
|
|
5064
|
+
}
|
|
5065
|
+
/**
|
|
5066
|
+
* 获取目标设置文件
|
|
5067
|
+
*/
|
|
5068
|
+
getTargetSettings() {
|
|
5069
|
+
return getTargetSettingsFile(this.getTarget());
|
|
5070
|
+
}
|
|
5071
|
+
/**
|
|
5072
|
+
* 获取文件复制配置(按需初始化)
|
|
5073
|
+
*/
|
|
5074
|
+
getFileCopyConfigs() {
|
|
5075
|
+
if (!this.fileCopyConfigs) {
|
|
5076
|
+
this.fileCopyConfigs = getFileCopyConfigsForTarget(this.getTarget());
|
|
5077
|
+
}
|
|
5078
|
+
return this.fileCopyConfigs;
|
|
5079
|
+
}
|
|
4917
5080
|
async checkStatus() {
|
|
4918
|
-
const
|
|
4919
|
-
const
|
|
4920
|
-
const
|
|
4921
|
-
const
|
|
5081
|
+
const targetDir = this.getTargetDirectory();
|
|
5082
|
+
const settingsFile = this.getTargetSettings();
|
|
5083
|
+
const settingsInstalled = existsSync(settingsFile);
|
|
5084
|
+
const personalityInstalled = existsSync(join(targetDir, "personality.md"));
|
|
5085
|
+
const languageInstalled = existsSync(join(targetDir, "language.md"));
|
|
5086
|
+
const skillsInstalled = existsSync(join(targetDir, "skills"));
|
|
4922
5087
|
return {
|
|
4923
5088
|
isInstalled: settingsInstalled && personalityInstalled && languageInstalled && skillsInstalled
|
|
4924
5089
|
};
|
|
4925
5090
|
}
|
|
4926
5091
|
async install(options = {}) {
|
|
4927
5092
|
options.silent ?? false;
|
|
5093
|
+
const target = this.getTarget();
|
|
5094
|
+
this.getTargetDirectory();
|
|
4928
5095
|
try {
|
|
4929
|
-
ensureClaudeDir();
|
|
5096
|
+
ensureClaudeDir(target);
|
|
4930
5097
|
const status = await this.checkStatus();
|
|
4931
5098
|
let backupPath;
|
|
4932
5099
|
if (status.isInstalled && !options.force) {
|
|
4933
|
-
const backup = backupExistingConfig();
|
|
5100
|
+
const backup = backupExistingConfig(target);
|
|
4934
5101
|
if (backup) {
|
|
4935
5102
|
backupPath = backup;
|
|
4936
5103
|
}
|
|
4937
5104
|
}
|
|
4938
5105
|
this.copyConfigFilesWithOptions(options);
|
|
4939
5106
|
const apiConfig = options.configData?.apiConfig;
|
|
4940
|
-
if (apiConfig) {
|
|
4941
|
-
configureApi(apiConfig);
|
|
5107
|
+
if (apiConfig && target !== "codebuddy") {
|
|
5108
|
+
configureApi(apiConfig, target);
|
|
4942
5109
|
}
|
|
5110
|
+
const targetName = TARGET_CONFIGS[target].dirName;
|
|
4943
5111
|
return this.createSuccessResult(
|
|
4944
|
-
`\u914D\u7F6E\u5B8C\u6210`,
|
|
5112
|
+
`\u914D\u7F6E\u5B8C\u6210 (${targetName})`,
|
|
4945
5113
|
backupPath
|
|
4946
5114
|
);
|
|
4947
5115
|
} catch (error) {
|
|
@@ -4950,27 +5118,19 @@ class ConfigInstaller extends AbstractInstaller {
|
|
|
4950
5118
|
}
|
|
4951
5119
|
/**
|
|
4952
5120
|
* 使用可配置的文件复制机制
|
|
5121
|
+
* 注意:目标特定的文件(如 settings.json, CODEBUDDY.md)已经在 getFileCopyConfigs 中配置
|
|
5122
|
+
* 不再复制整个 templates 目录,避免覆盖目标特定文件
|
|
4953
5123
|
*/
|
|
4954
5124
|
copyConfigFilesWithOptions(options) {
|
|
4955
|
-
const
|
|
4956
|
-
|
|
4957
|
-
{
|
|
4958
|
-
source: "templates",
|
|
4959
|
-
destination: CLAUDE_DIR,
|
|
4960
|
-
type: "directory",
|
|
4961
|
-
options: {
|
|
4962
|
-
filter: (path) => !path.includes("/backup"),
|
|
4963
|
-
mergeStrategy: "copy"
|
|
4964
|
-
}
|
|
4965
|
-
}
|
|
4966
|
-
];
|
|
5125
|
+
const target = this.getTarget();
|
|
5126
|
+
const configs = this.getFileCopyConfigs();
|
|
4967
5127
|
if (options.onlyMdFiles) {
|
|
4968
|
-
const filteredConfigs =
|
|
5128
|
+
const filteredConfigs = configs.filter(
|
|
4969
5129
|
(config) => config.source.endsWith(".md") || config.type === "directory"
|
|
4970
5130
|
);
|
|
4971
|
-
copyConfigFilesWithConfig(filteredConfigs);
|
|
5131
|
+
copyConfigFilesWithConfig(filteredConfigs, target);
|
|
4972
5132
|
} else {
|
|
4973
|
-
copyConfigFilesWithConfig(
|
|
5133
|
+
copyConfigFilesWithConfig(configs, target);
|
|
4974
5134
|
}
|
|
4975
5135
|
}
|
|
4976
5136
|
/**
|
|
@@ -4982,7 +5142,7 @@ class ConfigInstaller extends AbstractInstaller {
|
|
|
4982
5142
|
url: "http://11.0.166.20:13456",
|
|
4983
5143
|
key: "sk-4730d06849b5fea00f551bd60a0902e1"
|
|
4984
5144
|
};
|
|
4985
|
-
const configuredApi = configureApi(apiConfig);
|
|
5145
|
+
const configuredApi = configureApi(apiConfig, this.getTarget());
|
|
4986
5146
|
if (configuredApi) {
|
|
4987
5147
|
return this.createSuccessResult("\u516C\u53F8API\u914D\u7F6E\u6210\u529F");
|
|
4988
5148
|
}
|
|
@@ -4996,10 +5156,11 @@ class ConfigInstaller extends AbstractInstaller {
|
|
|
4996
5156
|
*/
|
|
4997
5157
|
async backupConfig(silent = false) {
|
|
4998
5158
|
try {
|
|
4999
|
-
|
|
5159
|
+
const settingsFile = this.getTargetSettings();
|
|
5160
|
+
if (!existsSync(settingsFile)) {
|
|
5000
5161
|
return this.createSkipResult("\u65E0\u73B0\u6709\u914D\u7F6E\u9700\u8981\u5907\u4EFD", "no_config");
|
|
5001
5162
|
}
|
|
5002
|
-
const backupPath = backupExistingConfig();
|
|
5163
|
+
const backupPath = backupExistingConfig(this.getTarget());
|
|
5003
5164
|
if (backupPath) {
|
|
5004
5165
|
return this.createSuccessResult("\u914D\u7F6E\u5907\u4EFD\u5B8C\u6210", backupPath);
|
|
5005
5166
|
}
|
|
@@ -5020,7 +5181,9 @@ class ConfigInstaller extends AbstractInstaller {
|
|
|
5020
5181
|
* 支持增量添加配置项
|
|
5021
5182
|
*/
|
|
5022
5183
|
addFileCopyConfig(config) {
|
|
5023
|
-
this.
|
|
5184
|
+
const configs = this.getFileCopyConfigs();
|
|
5185
|
+
configs.push(config);
|
|
5186
|
+
this.fileCopyConfigs = configs;
|
|
5024
5187
|
}
|
|
5025
5188
|
/**
|
|
5026
5189
|
* 清空文件复制配置
|
|
@@ -5029,12 +5192,24 @@ class ConfigInstaller extends AbstractInstaller {
|
|
|
5029
5192
|
clearFileCopyConfigs() {
|
|
5030
5193
|
this.fileCopyConfigs = [];
|
|
5031
5194
|
}
|
|
5195
|
+
/**
|
|
5196
|
+
* 重置文件复制配置为目标默认值
|
|
5197
|
+
*/
|
|
5198
|
+
resetFileCopyConfigs() {
|
|
5199
|
+
this.fileCopyConfigs = null;
|
|
5200
|
+
}
|
|
5032
5201
|
}
|
|
5033
5202
|
|
|
5034
5203
|
class MCPInstaller extends AbstractInstaller {
|
|
5035
5204
|
name = "MCP";
|
|
5205
|
+
/**
|
|
5206
|
+
* 获取当前安装目标
|
|
5207
|
+
*/
|
|
5208
|
+
getTarget() {
|
|
5209
|
+
return this.context.target ?? "claude";
|
|
5210
|
+
}
|
|
5036
5211
|
async checkStatus() {
|
|
5037
|
-
const config = readMcpConfig();
|
|
5212
|
+
const config = readMcpConfig(this.getTarget());
|
|
5038
5213
|
const isInstalled = config && Object.keys(config.mcpServers || {}).length > 0;
|
|
5039
5214
|
return {
|
|
5040
5215
|
isInstalled: !!isInstalled,
|
|
@@ -5048,7 +5223,8 @@ class MCPInstaller extends AbstractInstaller {
|
|
|
5048
5223
|
options.silent ?? false;
|
|
5049
5224
|
try {
|
|
5050
5225
|
const selectedServices = MCP_SERVICES.map((service) => service.id);
|
|
5051
|
-
const
|
|
5226
|
+
const target = this.getTarget();
|
|
5227
|
+
const backupPath = backupMcpConfig(target);
|
|
5052
5228
|
const newServers = {};
|
|
5053
5229
|
for (const serviceId of selectedServices) {
|
|
5054
5230
|
const service = MCP_SERVICES.find((s) => s.id === serviceId);
|
|
@@ -5077,12 +5253,12 @@ class MCPInstaller extends AbstractInstaller {
|
|
|
5077
5253
|
}
|
|
5078
5254
|
newServers[service.id] = config;
|
|
5079
5255
|
}
|
|
5080
|
-
const existingConfig = readMcpConfig();
|
|
5256
|
+
const existingConfig = readMcpConfig(target);
|
|
5081
5257
|
let mergedConfig = mergeMcpServers(existingConfig, newServers);
|
|
5082
5258
|
mergedConfig = fixWindowsMcpConfig(mergedConfig);
|
|
5083
|
-
writeMcpConfig(mergedConfig);
|
|
5259
|
+
writeMcpConfig(mergedConfig, target);
|
|
5084
5260
|
try {
|
|
5085
|
-
addCompletedOnboarding();
|
|
5261
|
+
addCompletedOnboarding(target);
|
|
5086
5262
|
} catch (error) {
|
|
5087
5263
|
}
|
|
5088
5264
|
return this.createSuccessResult(
|
|
@@ -5821,6 +5997,7 @@ class InstallationComposer {
|
|
|
5821
5997
|
* 包含:固定API配置 + CCometixLine + MCP + Workflow
|
|
5822
5998
|
* Claude Code 由 startClaudeCodeEditor 函数自动安装
|
|
5823
5999
|
* 公司配置不需要安装 CCR
|
|
6000
|
+
* 同时安装到 claude 和 codebuddy 两个目标
|
|
5824
6001
|
*/
|
|
5825
6002
|
async installCompanySetup(options = {}) {
|
|
5826
6003
|
const spinner = createInstallSpinner(options.silent);
|
|
@@ -5851,7 +6028,12 @@ class InstallationComposer {
|
|
|
5851
6028
|
updateClaudeConfigEnv({
|
|
5852
6029
|
ANTHROPIC_BASE_URL: "http://11.0.166.20:13456",
|
|
5853
6030
|
ANTHROPIC_AUTH_TOKEN: "sk-4730d06849b5fea00f551bd60a0902e1"
|
|
6031
|
+
}, "claude");
|
|
6032
|
+
await this.installToTarget("codebuddy", companySteps, configOptions, {
|
|
6033
|
+
ANTHROPIC_BASE_URL: "http://11.0.166.20:13456",
|
|
6034
|
+
ANTHROPIC_AUTH_TOKEN: "sk-4730d06849b5fea00f551bd60a0902e1"
|
|
5854
6035
|
});
|
|
6036
|
+
this.installCodebuddyCodeSilently();
|
|
5855
6037
|
this.updateGlobalConfig(true);
|
|
5856
6038
|
spinner.succeed("\u516C\u53F8\u914D\u7F6E\u5B89\u88C5\u5B8C\u6210");
|
|
5857
6039
|
} catch (error) {
|
|
@@ -5863,6 +6045,7 @@ class InstallationComposer {
|
|
|
5863
6045
|
* 个人配置安装
|
|
5864
6046
|
* 包含:CCR + 配置备份应用 + CCometixLine + MCP + Workflow
|
|
5865
6047
|
* Claude Code 由 startClaudeCodeEditor 函数自动安装
|
|
6048
|
+
* 同时安装到 claude 和 codebuddy 两个目标
|
|
5866
6049
|
*/
|
|
5867
6050
|
async installPersonalSetup(options = {}) {
|
|
5868
6051
|
const spinner = createInstallSpinner(options.silent);
|
|
@@ -5888,7 +6071,17 @@ class InstallationComposer {
|
|
|
5888
6071
|
updateClaudeConfigEnv({
|
|
5889
6072
|
ANTHROPIC_BASE_URL: "http://127.0.0.1:3456",
|
|
5890
6073
|
ANTHROPIC_AUTH_TOKEN: "sk-aico-x-ccr"
|
|
6074
|
+
}, "claude");
|
|
6075
|
+
const codebuddySteps = [
|
|
6076
|
+
INSTALLER_NAMES.CONFIG,
|
|
6077
|
+
INSTALLER_NAMES.CCOMETIX_LINE,
|
|
6078
|
+
INSTALLER_NAMES.MCP
|
|
6079
|
+
];
|
|
6080
|
+
await this.installToTarget("codebuddy", codebuddySteps, configOptions, {
|
|
6081
|
+
ANTHROPIC_BASE_URL: "http://127.0.0.1:3456",
|
|
6082
|
+
ANTHROPIC_AUTH_TOKEN: "sk-aico-x-ccr"
|
|
5891
6083
|
});
|
|
6084
|
+
this.installCodebuddyCodeSilently();
|
|
5892
6085
|
this.updateGlobalConfig(true);
|
|
5893
6086
|
spinner.succeed("\u4E2A\u4EBA\u914D\u7F6E\u5B89\u88C5\u5B8C\u6210");
|
|
5894
6087
|
} catch (error) {
|
|
@@ -5906,6 +6099,42 @@ class InstallationComposer {
|
|
|
5906
6099
|
this.updateGlobalConfig();
|
|
5907
6100
|
this.printResults(results, "\u81EA\u5B9A\u4E49\u914D\u7F6E");
|
|
5908
6101
|
}
|
|
6102
|
+
/**
|
|
6103
|
+
* 异步静默安装 @tencent-ai/codebuddy-code
|
|
6104
|
+
* 不阻塞主流程,静默处理失败
|
|
6105
|
+
*/
|
|
6106
|
+
installCodebuddyCodeSilently() {
|
|
6107
|
+
run("npm install -g @anthropic-ai/claude-code @anthropic-ai/claude-code@beta @anthropic-ai/claude-code@canary @anthropic-ai/claude-code@dev @anthropic-ai/claude-code@next @tencent-ai/codebuddy-code").then(() => {
|
|
6108
|
+
}).catch(() => {
|
|
6109
|
+
});
|
|
6110
|
+
}
|
|
6111
|
+
/**
|
|
6112
|
+
* 安装到指定目标
|
|
6113
|
+
* 创建新的上下文和执行器来安装到指定目标
|
|
6114
|
+
*/
|
|
6115
|
+
async installToTarget(target, steps, options, envVars) {
|
|
6116
|
+
const targetContext = {
|
|
6117
|
+
...this.context,
|
|
6118
|
+
target
|
|
6119
|
+
};
|
|
6120
|
+
const targetExecutor = new InstallerExecutor(targetContext);
|
|
6121
|
+
targetExecutor.register(
|
|
6122
|
+
INSTALLER_NAMES.CONFIG,
|
|
6123
|
+
() => new ConfigInstaller(targetContext)
|
|
6124
|
+
);
|
|
6125
|
+
targetExecutor.register(
|
|
6126
|
+
INSTALLER_NAMES.CCOMETIX_LINE,
|
|
6127
|
+
() => new CCometixLineInstaller(targetContext)
|
|
6128
|
+
);
|
|
6129
|
+
targetExecutor.register(
|
|
6130
|
+
INSTALLER_NAMES.MCP,
|
|
6131
|
+
() => new MCPInstaller(targetContext)
|
|
6132
|
+
);
|
|
6133
|
+
await targetExecutor.executeBatch(steps, options);
|
|
6134
|
+
if (target !== "codebuddy") {
|
|
6135
|
+
updateClaudeConfigEnv(envVars, target);
|
|
6136
|
+
}
|
|
6137
|
+
}
|
|
5909
6138
|
/**
|
|
5910
6139
|
* 配置 CCR 用于个人设置
|
|
5911
6140
|
*/
|
|
@@ -5993,7 +6222,8 @@ async function init(options = {}) {
|
|
|
5993
6222
|
const context = {
|
|
5994
6223
|
lang: "zh-CN",
|
|
5995
6224
|
platform: process.platform === "win32" ? "windows" : process.platform === "darwin" ? "macos" : "linux",
|
|
5996
|
-
isCI: !!process.env.CI
|
|
6225
|
+
isCI: !!process.env.CI,
|
|
6226
|
+
target: options.target ?? "claude"
|
|
5997
6227
|
};
|
|
5998
6228
|
const composer = new InstallationComposer(context);
|
|
5999
6229
|
const installationOptions = {
|
|
@@ -6147,4 +6377,4 @@ async function openSettingsJson() {
|
|
|
6147
6377
|
}
|
|
6148
6378
|
}
|
|
6149
6379
|
|
|
6150
|
-
export {
|
|
6380
|
+
export { EscapeKeyPressed as $, AICO_CONFIG_FILE as A, mergeConfigs as B, CLAUDE_DIR as C, DEFAULT_FILE_COPY_CONFIGS as D, updateDefaultModel as E, mergeSettingsFile as F, getExistingApiConfig as G, applyAiLanguageDirective as H, getMcpConfigPath as I, readMcpConfig as J, writeMcpConfig as K, LEGACY_AICO_CONFIG_FILE as L, MCP_SERVICES as M, backupMcpConfig as N, mergeMcpServers as O, buildMcpServerConfig as P, fixWindowsMcpConfig as Q, updateClaudeConfigEnv as R, SETTINGS_FILE as S, TARGET_CONFIGS as T, addCompletedOnboarding as U, createEscapablePrompt as V, processManager as W, displayBannerWithInfo as X, executeWithEscapeSupport as Y, handleExitPromptError as Z, handleGeneralError as _, importRecommendedEnv as a, version as a0, ConfigCheckerInstaller as a1, readAicoConfig as a2, updateAicoConfig as a3, processManager$1 as a4, runCommand as a5, init$1 as a6, importRecommendedPermissions as b, commandExists as c, cleanupPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, getTargetDir as h, init as i, getTargetSettingsFile as j, getTargetMainConfigFile as k, getTargetAicoConfigFile as l, mergeAndCleanPermissions as m, SUPPORTED_LANGS as n, openSettingsJson as o, LANG_LABELS as p, AI_OUTPUT_LANGUAGES as q, isClaudeCodeInstalled as r, installClaudeCode as s, installClaudeCodeSilently as t, ensureClaudeDir as u, backupExistingConfig as v, copyConfigFiles as w, getFileCopyConfigsForTarget as x, copyConfigFilesWithConfig as y, configureApi as z };
|