codemate-ai 1.0.6 → 1.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/dist/cli.js +526 -196
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import * as fs21 from 'fs';
|
|
|
5
5
|
import fs21__default, { existsSync, statSync, promises } from 'fs';
|
|
6
6
|
import * as path18 from 'pathe';
|
|
7
7
|
import { join, resolve, extname, basename } from 'pathe';
|
|
8
|
-
import React, { createContext, useState, useRef,
|
|
8
|
+
import React, { createContext, useState, useRef, useCallback, useEffect, useMemo, useContext } from 'react';
|
|
9
9
|
import { render, useApp, useInput, Box, Text } from 'ink';
|
|
10
10
|
import Spinner3 from 'ink-spinner';
|
|
11
11
|
import defu from 'defu';
|
|
@@ -384,10 +384,14 @@ var init_ConfigManager = __esm({
|
|
|
384
384
|
constructor(options) {
|
|
385
385
|
const { cwd, productName, argvConfig = {} } = options;
|
|
386
386
|
const lowerProductName = productName.toLowerCase();
|
|
387
|
+
const legacyGlobalConfigPath = path18.join(homedir(), ".aiclirc.json");
|
|
387
388
|
this.globalConfigPath = path18.join(homedir(), `.${lowerProductName}`, "config.json");
|
|
388
389
|
this.projectConfigPath = path18.join(cwd, `.${lowerProductName}`, "config.json");
|
|
389
390
|
const projectLocalConfigPath = path18.join(cwd, `.${lowerProductName}`, "config.local.json");
|
|
390
|
-
this.globalConfig =
|
|
391
|
+
this.globalConfig = defu(
|
|
392
|
+
this.loadConfig(this.globalConfigPath),
|
|
393
|
+
this.loadConfig(legacyGlobalConfigPath)
|
|
394
|
+
);
|
|
391
395
|
this.projectConfig = defu(
|
|
392
396
|
this.loadConfig(projectLocalConfigPath),
|
|
393
397
|
// 优先级高
|
|
@@ -423,6 +427,7 @@ var init_ConfigManager = __esm({
|
|
|
423
427
|
)
|
|
424
428
|
)
|
|
425
429
|
);
|
|
430
|
+
this.normalizeConfig(config);
|
|
426
431
|
config.planModel = config.planModel || config.model;
|
|
427
432
|
config.smallModel = config.smallModel || config.model;
|
|
428
433
|
config.visionModel = config.visionModel || config.model;
|
|
@@ -485,6 +490,26 @@ var init_ConfigManager = __esm({
|
|
|
485
490
|
return {};
|
|
486
491
|
}
|
|
487
492
|
}
|
|
493
|
+
normalizeConfig(config) {
|
|
494
|
+
const legacyModel = config.model;
|
|
495
|
+
if (!legacyModel || typeof legacyModel !== "object") {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const modelName = typeof legacyModel.model === "string" ? legacyModel.model : "deepseek-chat";
|
|
499
|
+
const providerKey = config._metadata?.provider || "deepseek";
|
|
500
|
+
config.model = modelName;
|
|
501
|
+
if (!config.provider) {
|
|
502
|
+
config.provider = {};
|
|
503
|
+
}
|
|
504
|
+
const existingProvider = config.provider[providerKey] || {};
|
|
505
|
+
config.provider[providerKey] = {
|
|
506
|
+
apiKey: existingProvider.apiKey || legacyModel.apiKey,
|
|
507
|
+
baseURL: existingProvider.baseURL || legacyModel.baseURL
|
|
508
|
+
};
|
|
509
|
+
if (config.temperature === void 0 && legacyModel.temperature !== void 0) {
|
|
510
|
+
config.temperature = legacyModel.temperature;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
488
513
|
/**
|
|
489
514
|
* 保存配置文件
|
|
490
515
|
*
|
|
@@ -714,36 +739,43 @@ var init_WorkspaceCommand = __esm({
|
|
|
714
739
|
super();
|
|
715
740
|
this.configManager = configManager;
|
|
716
741
|
}
|
|
717
|
-
async execute(args) {
|
|
742
|
+
async execute(args, app) {
|
|
718
743
|
const subcommand = args[0];
|
|
744
|
+
const sessionService = app.getContainer().get("session");
|
|
719
745
|
try {
|
|
720
746
|
switch (subcommand) {
|
|
721
747
|
case "create":
|
|
722
|
-
await this.create(this.parseCreateOptions(args.slice(1)));
|
|
748
|
+
await this.create(this.parseCreateOptions(args.slice(1)), sessionService);
|
|
723
749
|
break;
|
|
724
750
|
case "list":
|
|
725
|
-
await this.list();
|
|
751
|
+
await this.list(sessionService);
|
|
726
752
|
break;
|
|
727
753
|
case "remove":
|
|
728
754
|
case "delete":
|
|
729
|
-
await this.remove(args[1]);
|
|
755
|
+
await this.remove(args[1], sessionService);
|
|
730
756
|
break;
|
|
731
757
|
case "complete":
|
|
732
|
-
await this.complete();
|
|
758
|
+
await this.complete(sessionService);
|
|
733
759
|
break;
|
|
734
760
|
default:
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
761
|
+
await this.output(
|
|
762
|
+
sessionService,
|
|
763
|
+
[
|
|
764
|
+
"Usage: /workspace <create|list|remove|complete> [options]",
|
|
765
|
+
"",
|
|
766
|
+
"Commands:",
|
|
767
|
+
" create [--name <name>] [-b <branch>] Create a new workspace",
|
|
768
|
+
" list List all workspaces",
|
|
769
|
+
" remove <name> Remove a workspace",
|
|
770
|
+
" complete Complete and merge current workspace"
|
|
771
|
+
].join("\n")
|
|
743
772
|
);
|
|
744
773
|
}
|
|
745
774
|
} catch (error) {
|
|
746
|
-
|
|
775
|
+
await this.output(
|
|
776
|
+
sessionService,
|
|
777
|
+
`\u274C Error: ${error instanceof Error ? error.message : String(error)}`
|
|
778
|
+
);
|
|
747
779
|
}
|
|
748
780
|
}
|
|
749
781
|
/**
|
|
@@ -771,110 +803,121 @@ var init_WorkspaceCommand = __esm({
|
|
|
771
803
|
/**
|
|
772
804
|
* 创建工作区
|
|
773
805
|
*/
|
|
774
|
-
async create(options) {
|
|
806
|
+
async create(options, sessionService) {
|
|
775
807
|
const workspaceName = options.name;
|
|
776
808
|
if (!workspaceName) {
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
809
|
+
await this.output(
|
|
810
|
+
sessionService,
|
|
811
|
+
[
|
|
812
|
+
"\u274C Workspace name is required",
|
|
813
|
+
"Usage: /workspace create --name <workspace-name> [-b <branch>]",
|
|
814
|
+
"",
|
|
815
|
+
"Example:",
|
|
816
|
+
" /workspace create --name feature-auth",
|
|
817
|
+
" /workspace create --name bugfix-login -b develop"
|
|
818
|
+
].join("\n")
|
|
819
|
+
);
|
|
783
820
|
return;
|
|
784
821
|
}
|
|
785
822
|
const config = this.configManager.config;
|
|
786
823
|
const baseBranch = options.baseBranch || config.workspace?.baseBranch || "main";
|
|
787
824
|
if (!this.branchExists(baseBranch)) {
|
|
788
|
-
|
|
789
|
-
|
|
825
|
+
let message = `\u274C Base branch '${baseBranch}' does not exist
|
|
826
|
+
Available branches:`;
|
|
790
827
|
try {
|
|
791
828
|
const branches = this.execGit("branch -a").split("\n").map(
|
|
792
829
|
(line) => line.trim().replace(/^\*\s*/, "").replace(/^remotes\/origin\//, "")
|
|
793
830
|
).filter((line) => line && !line.includes("HEAD")).slice(0, 5);
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
}
|
|
831
|
+
message += `
|
|
832
|
+
${branches.map((branch) => ` - ${branch}`).join("\n")}`;
|
|
797
833
|
} catch {
|
|
798
|
-
|
|
834
|
+
message += "\n (Unable to list branches)";
|
|
799
835
|
}
|
|
836
|
+
await this.output(sessionService, message);
|
|
800
837
|
return;
|
|
801
838
|
}
|
|
802
839
|
const workspacePath = this.getWorkspacePath(workspaceName);
|
|
803
840
|
if (existsSync(workspacePath)) {
|
|
804
|
-
|
|
841
|
+
await this.output(sessionService, `\u274C Workspace already exists: ${workspacePath}`);
|
|
805
842
|
return;
|
|
806
843
|
}
|
|
807
844
|
const branchExists = this.branchExists(workspaceName);
|
|
808
|
-
|
|
845
|
+
await this.output(sessionService, `\u{1F33F} Creating workspace '${workspaceName}'...`);
|
|
809
846
|
try {
|
|
810
847
|
if (branchExists && !options.newBranch) {
|
|
811
848
|
this.execGit(`worktree add ${workspacePath} ${workspaceName}`);
|
|
812
849
|
} else {
|
|
813
850
|
this.execGit(`worktree add -b ${workspaceName} ${workspacePath} ${baseBranch}`);
|
|
814
851
|
}
|
|
815
|
-
|
|
816
|
-
|
|
852
|
+
await this.output(
|
|
853
|
+
sessionService,
|
|
854
|
+
`\u2705 Workspace created at: ${workspacePath}
|
|
855
|
+
\u{1F4A1} To start working: cd ${workspacePath}`
|
|
856
|
+
);
|
|
817
857
|
} catch (error) {
|
|
818
|
-
|
|
858
|
+
await this.output(sessionService, "\u274C Failed to create workspace");
|
|
819
859
|
throw error;
|
|
820
860
|
}
|
|
821
861
|
}
|
|
822
862
|
/**
|
|
823
863
|
* 列出所有工作区
|
|
824
864
|
*/
|
|
825
|
-
async list() {
|
|
865
|
+
async list(sessionService) {
|
|
826
866
|
try {
|
|
827
867
|
const output = this.execGit("worktree list --porcelain");
|
|
828
868
|
const workspaces = this.parseWorktreeList(output);
|
|
829
869
|
if (workspaces.length === 0) {
|
|
830
|
-
|
|
870
|
+
await this.output(sessionService, "\u{1F4CB} No workspaces found");
|
|
831
871
|
return;
|
|
832
872
|
}
|
|
833
|
-
|
|
873
|
+
const lines = ["\u{1F4CB} Workspaces:", ""];
|
|
834
874
|
for (const workspace of workspaces) {
|
|
835
875
|
const marker = workspace.isCurrent ? "\u2192" : " ";
|
|
836
876
|
const name = basename(workspace.path);
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
877
|
+
lines.push(`${marker} ${name}`);
|
|
878
|
+
lines.push(` Path: ${workspace.path}`);
|
|
879
|
+
lines.push(` Branch: ${workspace.branch}`);
|
|
880
|
+
lines.push(` Commit: ${workspace.commit.substring(0, 7)}`);
|
|
881
|
+
lines.push("");
|
|
842
882
|
}
|
|
883
|
+
await this.output(sessionService, lines.join("\n").trimEnd());
|
|
843
884
|
} catch (error) {
|
|
844
|
-
|
|
885
|
+
await this.output(sessionService, "\u274C Failed to list workspaces");
|
|
845
886
|
throw error;
|
|
846
887
|
}
|
|
847
888
|
}
|
|
848
889
|
/**
|
|
849
890
|
* 删除工作区
|
|
850
891
|
*/
|
|
851
|
-
async remove(name) {
|
|
892
|
+
async remove(name, sessionService) {
|
|
852
893
|
if (!name) {
|
|
853
|
-
|
|
854
|
-
|
|
894
|
+
await this.output(
|
|
895
|
+
sessionService,
|
|
896
|
+
"\u274C Workspace name is required\nUsage: /workspace remove <name>"
|
|
897
|
+
);
|
|
855
898
|
return;
|
|
856
899
|
}
|
|
857
900
|
const workspacePath = this.getWorkspacePath(name);
|
|
858
901
|
if (!existsSync(workspacePath)) {
|
|
859
|
-
|
|
902
|
+
await this.output(sessionService, `\u274C Workspace not found: ${workspacePath}`);
|
|
860
903
|
return;
|
|
861
904
|
}
|
|
862
|
-
|
|
905
|
+
await this.output(sessionService, `\u{1F5D1}\uFE0F Removing workspace '${name}'...`);
|
|
863
906
|
try {
|
|
864
907
|
this.execGit(`worktree remove ${workspacePath}`);
|
|
865
|
-
|
|
908
|
+
await this.output(sessionService, `\u2705 Workspace removed: ${workspacePath}`);
|
|
866
909
|
} catch (error) {
|
|
867
|
-
|
|
910
|
+
await this.output(sessionService, "\u274C Failed to remove workspace");
|
|
868
911
|
throw error;
|
|
869
912
|
}
|
|
870
913
|
}
|
|
871
914
|
/**
|
|
872
915
|
* 完成并合并工作区
|
|
873
916
|
*/
|
|
874
|
-
async complete() {
|
|
917
|
+
async complete(sessionService) {
|
|
875
918
|
const currentBranch = this.getCurrentBranch();
|
|
876
919
|
if (!currentBranch) {
|
|
877
|
-
|
|
920
|
+
await this.output(sessionService, "\u274C Not in a Git repository");
|
|
878
921
|
return;
|
|
879
922
|
}
|
|
880
923
|
const config = this.configManager.config;
|
|
@@ -883,28 +926,41 @@ var init_WorkspaceCommand = __esm({
|
|
|
883
926
|
try {
|
|
884
927
|
this.execGit("diff-index --quiet HEAD --");
|
|
885
928
|
} catch {
|
|
886
|
-
|
|
929
|
+
await this.output(
|
|
930
|
+
sessionService,
|
|
931
|
+
"\u274C You have uncommitted changes. Please commit or stash them first."
|
|
932
|
+
);
|
|
887
933
|
return;
|
|
888
934
|
}
|
|
889
|
-
|
|
935
|
+
await this.output(sessionService, `\u{1F500} Merging ${currentBranch} into ${baseBranch}...`);
|
|
890
936
|
try {
|
|
891
937
|
this.execGit(`checkout ${baseBranch}`);
|
|
892
938
|
this.execGit(`merge ${currentBranch}`);
|
|
893
|
-
|
|
939
|
+
await this.output(sessionService, `\u2705 Merged ${currentBranch} into ${baseBranch}`);
|
|
894
940
|
const workspacePath = process.cwd();
|
|
895
|
-
|
|
941
|
+
await this.output(sessionService, "\u{1F5D1}\uFE0F Removing workspace...");
|
|
896
942
|
process.chdir("..");
|
|
897
943
|
this.execGit(`worktree remove ${workspacePath}`);
|
|
898
944
|
if (autoDelete) {
|
|
899
|
-
|
|
945
|
+
await this.output(sessionService, `\u{1F5D1}\uFE0F Deleting branch ${currentBranch}...`);
|
|
900
946
|
this.execGit(`branch -d ${currentBranch}`);
|
|
901
947
|
}
|
|
902
|
-
|
|
948
|
+
await this.output(sessionService, "\u2705 Workspace completed and merged!");
|
|
903
949
|
} catch (error) {
|
|
904
|
-
|
|
950
|
+
await this.output(sessionService, "\u274C Failed to complete workspace");
|
|
905
951
|
throw error;
|
|
906
952
|
}
|
|
907
953
|
}
|
|
954
|
+
async output(sessionService, message) {
|
|
955
|
+
if (sessionService) {
|
|
956
|
+
await sessionService.addMessage({
|
|
957
|
+
role: "assistant",
|
|
958
|
+
content: message
|
|
959
|
+
});
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
console.log(message);
|
|
963
|
+
}
|
|
908
964
|
/**
|
|
909
965
|
* 获取项目名称
|
|
910
966
|
*/
|
|
@@ -8680,7 +8736,6 @@ var SessionService = class {
|
|
|
8680
8736
|
}
|
|
8681
8737
|
/**
|
|
8682
8738
|
* 清除当前会话并创建新会话
|
|
8683
|
-
* 对标Neovate的clear命令功能
|
|
8684
8739
|
*/
|
|
8685
8740
|
async clear() {
|
|
8686
8741
|
const newSession = await this.create();
|
|
@@ -9504,6 +9559,11 @@ var ExitCommand = class extends SlashCommand {
|
|
|
9504
9559
|
description = "Exit the program";
|
|
9505
9560
|
aliases = ["quit", "q"];
|
|
9506
9561
|
async execute(_args, app) {
|
|
9562
|
+
const eventBus = app.getContainer().get("eventBus");
|
|
9563
|
+
if (eventBus.listenerCount("exit_app") > 0) {
|
|
9564
|
+
eventBus.emit("exit_app");
|
|
9565
|
+
return;
|
|
9566
|
+
}
|
|
9507
9567
|
console.log("\u{1F44B} Goodbye!");
|
|
9508
9568
|
await app.stop();
|
|
9509
9569
|
process.exit(0);
|
|
@@ -9622,8 +9682,9 @@ var ConfigCommand = class extends SlashCommand {
|
|
|
9622
9682
|
*/
|
|
9623
9683
|
async execute(args, app) {
|
|
9624
9684
|
const configService = app.getContainer().get("config");
|
|
9685
|
+
const sessionService = app.getContainer().get("session");
|
|
9625
9686
|
if (!configService) {
|
|
9626
|
-
|
|
9687
|
+
await this.outputResult(sessionService, "\u274C ConfigService not available");
|
|
9627
9688
|
return;
|
|
9628
9689
|
}
|
|
9629
9690
|
const [action, ...rest] = args;
|
|
@@ -9647,6 +9708,16 @@ var ConfigCommand = class extends SlashCommand {
|
|
|
9647
9708
|
default:
|
|
9648
9709
|
result = this.getHelp();
|
|
9649
9710
|
}
|
|
9711
|
+
await this.outputResult(sessionService, result);
|
|
9712
|
+
}
|
|
9713
|
+
async outputResult(sessionService, result) {
|
|
9714
|
+
if (sessionService) {
|
|
9715
|
+
await sessionService.addMessage({
|
|
9716
|
+
role: "assistant",
|
|
9717
|
+
content: result
|
|
9718
|
+
});
|
|
9719
|
+
return;
|
|
9720
|
+
}
|
|
9650
9721
|
console.log(result);
|
|
9651
9722
|
}
|
|
9652
9723
|
/**
|
|
@@ -9809,17 +9880,17 @@ var ForkCommand = class extends SlashCommand {
|
|
|
9809
9880
|
async execute(args, app) {
|
|
9810
9881
|
const sessionService = app.getContainer().get("session");
|
|
9811
9882
|
if (!sessionService) {
|
|
9812
|
-
|
|
9883
|
+
await this.output(void 0, "\u274C SessionService not available");
|
|
9813
9884
|
return;
|
|
9814
9885
|
}
|
|
9815
9886
|
const currentSession = sessionService.getCurrent();
|
|
9816
9887
|
if (!currentSession) {
|
|
9817
|
-
|
|
9888
|
+
await this.output(sessionService, "\u274C No active session");
|
|
9818
9889
|
return;
|
|
9819
9890
|
}
|
|
9820
9891
|
const messages = currentSession.messages;
|
|
9821
9892
|
if (messages.length === 0) {
|
|
9822
|
-
|
|
9893
|
+
await this.output(sessionService, "\u274C No messages to fork from");
|
|
9823
9894
|
return;
|
|
9824
9895
|
}
|
|
9825
9896
|
if (args.length > 0) {
|
|
@@ -9827,7 +9898,7 @@ var ForkCommand = class extends SlashCommand {
|
|
|
9827
9898
|
await this.forkFromMessage(sessionService, messageUuid);
|
|
9828
9899
|
return;
|
|
9829
9900
|
}
|
|
9830
|
-
this.showForkSelector(messages);
|
|
9901
|
+
await this.showForkSelector(sessionService, messages);
|
|
9831
9902
|
}
|
|
9832
9903
|
/**
|
|
9833
9904
|
* 从指定消息分叉
|
|
@@ -9837,27 +9908,36 @@ var ForkCommand = class extends SlashCommand {
|
|
|
9837
9908
|
const newSession = await sessionService.fork({
|
|
9838
9909
|
fromMessageUuid: messageUuid
|
|
9839
9910
|
});
|
|
9840
|
-
|
|
9841
|
-
|
|
9911
|
+
await this.output(
|
|
9912
|
+
sessionService,
|
|
9913
|
+
`\u2705 Session forked: ${newSession.id}
|
|
9914
|
+
Use /sessions to switch to it.`
|
|
9915
|
+
);
|
|
9842
9916
|
} catch (error) {
|
|
9843
|
-
|
|
9917
|
+
await this.output(
|
|
9918
|
+
sessionService,
|
|
9919
|
+
`\u274C Fork failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
9920
|
+
);
|
|
9844
9921
|
}
|
|
9845
9922
|
}
|
|
9846
9923
|
/**
|
|
9847
9924
|
* 显示分叉选择器
|
|
9848
9925
|
*/
|
|
9849
|
-
showForkSelector(messages) {
|
|
9926
|
+
async showForkSelector(sessionService, messages) {
|
|
9850
9927
|
const messagesWithUuid = messages.filter((msg) => msg.uuid);
|
|
9851
9928
|
if (messagesWithUuid.length === 0) {
|
|
9852
|
-
|
|
9853
|
-
|
|
9929
|
+
await this.output(
|
|
9930
|
+
sessionService,
|
|
9931
|
+
"\u274C No messages with UUID found. Fork requires enhanced messages.\n\u{1F4A1} Tip: New messages will have UUIDs automatically."
|
|
9932
|
+
);
|
|
9854
9933
|
return;
|
|
9855
9934
|
}
|
|
9856
9935
|
const messageList = messagesWithUuid.map((msg, index) => {
|
|
9857
9936
|
const preview = this.getMessagePreview(msg);
|
|
9858
9937
|
return `${index + 1}. [${msg.uuid.slice(0, 8)}] ${msg.role}: ${preview}`;
|
|
9859
9938
|
}).join("\n");
|
|
9860
|
-
|
|
9939
|
+
await this.output(
|
|
9940
|
+
sessionService,
|
|
9861
9941
|
`
|
|
9862
9942
|
\u{1F4CB} Select a message to fork from:
|
|
9863
9943
|
|
|
@@ -9869,6 +9949,16 @@ Example: /fork ${messagesWithUuid[0].uuid}
|
|
|
9869
9949
|
`.trim()
|
|
9870
9950
|
);
|
|
9871
9951
|
}
|
|
9952
|
+
async output(sessionService, message) {
|
|
9953
|
+
if (sessionService) {
|
|
9954
|
+
await sessionService.addMessage({
|
|
9955
|
+
role: "assistant",
|
|
9956
|
+
content: message
|
|
9957
|
+
});
|
|
9958
|
+
return;
|
|
9959
|
+
}
|
|
9960
|
+
console.log(message);
|
|
9961
|
+
}
|
|
9872
9962
|
/**
|
|
9873
9963
|
* 获取消息预览
|
|
9874
9964
|
*/
|
|
@@ -18156,22 +18246,23 @@ var SkillCommand = class extends SlashCommand {
|
|
|
18156
18246
|
*
|
|
18157
18247
|
* @param args 命令参数
|
|
18158
18248
|
*/
|
|
18159
|
-
async execute(args) {
|
|
18249
|
+
async execute(args, app) {
|
|
18160
18250
|
const subcommand = args[0];
|
|
18251
|
+
const sessionService = app.getContainer().get("session");
|
|
18161
18252
|
switch (subcommand) {
|
|
18162
18253
|
case "add":
|
|
18163
|
-
await this.handleAdd(args.slice(1));
|
|
18254
|
+
await this.handleAdd(args.slice(1), sessionService);
|
|
18164
18255
|
break;
|
|
18165
18256
|
case "remove":
|
|
18166
18257
|
case "rm":
|
|
18167
|
-
await this.handleRemove(args.slice(1));
|
|
18258
|
+
await this.handleRemove(args.slice(1), sessionService);
|
|
18168
18259
|
break;
|
|
18169
18260
|
case "list":
|
|
18170
18261
|
case "ls":
|
|
18171
|
-
await this.handleList();
|
|
18262
|
+
await this.handleList(sessionService);
|
|
18172
18263
|
break;
|
|
18173
18264
|
default:
|
|
18174
|
-
this.showHelp();
|
|
18265
|
+
await this.showHelp(sessionService);
|
|
18175
18266
|
}
|
|
18176
18267
|
}
|
|
18177
18268
|
/**
|
|
@@ -18179,10 +18270,12 @@ var SkillCommand = class extends SlashCommand {
|
|
|
18179
18270
|
*
|
|
18180
18271
|
* 从 GitHub 安装技能
|
|
18181
18272
|
*/
|
|
18182
|
-
async handleAdd(args) {
|
|
18273
|
+
async handleAdd(args, sessionService) {
|
|
18183
18274
|
if (args.length === 0) {
|
|
18184
|
-
|
|
18185
|
-
|
|
18275
|
+
await this.output(
|
|
18276
|
+
sessionService,
|
|
18277
|
+
"Error: GitHub source is required\nUsage: /skill add <user/repo> [--name <name>] [--overwrite]"
|
|
18278
|
+
);
|
|
18186
18279
|
return;
|
|
18187
18280
|
}
|
|
18188
18281
|
const source = args[0];
|
|
@@ -18198,8 +18291,12 @@ var SkillCommand = class extends SlashCommand {
|
|
|
18198
18291
|
}
|
|
18199
18292
|
try {
|
|
18200
18293
|
await this.skillManager.addSkill(source, options);
|
|
18294
|
+
await this.output(
|
|
18295
|
+
sessionService,
|
|
18296
|
+
`\u2705 Skill installed: ${options.name || source.split("/").pop() || source}`
|
|
18297
|
+
);
|
|
18201
18298
|
} catch (error) {
|
|
18202
|
-
|
|
18299
|
+
await this.output(sessionService, `Error: ${error}`);
|
|
18203
18300
|
}
|
|
18204
18301
|
}
|
|
18205
18302
|
/**
|
|
@@ -18207,17 +18304,20 @@ var SkillCommand = class extends SlashCommand {
|
|
|
18207
18304
|
*
|
|
18208
18305
|
* 删除已安装的技能
|
|
18209
18306
|
*/
|
|
18210
|
-
async handleRemove(args) {
|
|
18307
|
+
async handleRemove(args, sessionService) {
|
|
18211
18308
|
if (args.length === 0) {
|
|
18212
|
-
|
|
18213
|
-
|
|
18309
|
+
await this.output(
|
|
18310
|
+
sessionService,
|
|
18311
|
+
"Error: Skill name is required\nUsage: /skill remove <name>"
|
|
18312
|
+
);
|
|
18214
18313
|
return;
|
|
18215
18314
|
}
|
|
18216
18315
|
const name = args[0];
|
|
18217
18316
|
try {
|
|
18218
18317
|
await this.skillManager.removeSkill(name);
|
|
18318
|
+
await this.output(sessionService, `\u2705 Skill removed: ${name}`);
|
|
18219
18319
|
} catch (error) {
|
|
18220
|
-
|
|
18320
|
+
await this.output(sessionService, `Error: ${error}`);
|
|
18221
18321
|
}
|
|
18222
18322
|
}
|
|
18223
18323
|
/**
|
|
@@ -18225,25 +18325,28 @@ var SkillCommand = class extends SlashCommand {
|
|
|
18225
18325
|
*
|
|
18226
18326
|
* 列出所有可用的技能
|
|
18227
18327
|
*/
|
|
18228
|
-
async handleList() {
|
|
18328
|
+
async handleList(sessionService) {
|
|
18229
18329
|
const skills = this.skillManager.listSkills();
|
|
18230
18330
|
if (skills.length === 0) {
|
|
18231
|
-
|
|
18331
|
+
await this.output(sessionService, "No skills found");
|
|
18232
18332
|
return;
|
|
18233
18333
|
}
|
|
18234
|
-
|
|
18334
|
+
const lines = ["Available Skills:", ""];
|
|
18235
18335
|
for (const skill of skills) {
|
|
18236
|
-
|
|
18237
|
-
|
|
18238
|
-
|
|
18239
|
-
|
|
18336
|
+
lines.push(` /${skill.name}`);
|
|
18337
|
+
lines.push(` ${skill.description}`);
|
|
18338
|
+
lines.push(` Source: ${skill.source}`);
|
|
18339
|
+
lines.push("");
|
|
18240
18340
|
}
|
|
18341
|
+
await this.output(sessionService, lines.join("\n").trimEnd());
|
|
18241
18342
|
}
|
|
18242
18343
|
/**
|
|
18243
18344
|
* 显示帮助信息
|
|
18244
18345
|
*/
|
|
18245
|
-
showHelp() {
|
|
18246
|
-
|
|
18346
|
+
async showHelp(sessionService) {
|
|
18347
|
+
await this.output(
|
|
18348
|
+
sessionService,
|
|
18349
|
+
`
|
|
18247
18350
|
Usage: /skill <subcommand> [options]
|
|
18248
18351
|
|
|
18249
18352
|
Subcommands:
|
|
@@ -18257,7 +18360,18 @@ Examples:
|
|
|
18257
18360
|
/skill add user/repo --name my-skill --overwrite
|
|
18258
18361
|
/skill remove my-skill
|
|
18259
18362
|
/skill list
|
|
18260
|
-
|
|
18363
|
+
`.trim()
|
|
18364
|
+
);
|
|
18365
|
+
}
|
|
18366
|
+
async output(sessionService, message) {
|
|
18367
|
+
if (sessionService) {
|
|
18368
|
+
await sessionService.addMessage({
|
|
18369
|
+
role: "assistant",
|
|
18370
|
+
content: message
|
|
18371
|
+
});
|
|
18372
|
+
return;
|
|
18373
|
+
}
|
|
18374
|
+
console.log(message);
|
|
18261
18375
|
}
|
|
18262
18376
|
};
|
|
18263
18377
|
|
|
@@ -18273,86 +18387,95 @@ var AgentCommand = class extends SlashCommand {
|
|
|
18273
18387
|
super();
|
|
18274
18388
|
this.agentManager = agentManager;
|
|
18275
18389
|
}
|
|
18276
|
-
async execute(args) {
|
|
18390
|
+
async execute(args, app) {
|
|
18391
|
+
const sessionService = app.getContainer().get("session");
|
|
18277
18392
|
if (args.length === 0) {
|
|
18278
|
-
this.showHelp();
|
|
18393
|
+
await this.showHelp(sessionService);
|
|
18279
18394
|
return;
|
|
18280
18395
|
}
|
|
18281
18396
|
const subcommand = args[0];
|
|
18282
18397
|
if (subcommand === "list") {
|
|
18283
|
-
this.listAgents();
|
|
18398
|
+
await this.listAgents(sessionService);
|
|
18284
18399
|
return;
|
|
18285
18400
|
}
|
|
18286
18401
|
const agentName = subcommand;
|
|
18287
18402
|
const goal = args.slice(1).join(" ");
|
|
18288
18403
|
if (!goal) {
|
|
18289
|
-
|
|
18290
|
-
|
|
18404
|
+
await this.output(
|
|
18405
|
+
sessionService,
|
|
18406
|
+
`\u274C Please provide a goal for the agent
|
|
18407
|
+
Usage: /agent ${agentName} <goal>`
|
|
18408
|
+
);
|
|
18291
18409
|
return;
|
|
18292
18410
|
}
|
|
18293
|
-
await this.delegateTask(agentName, goal);
|
|
18411
|
+
await this.delegateTask(agentName, goal, sessionService);
|
|
18294
18412
|
}
|
|
18295
18413
|
/**
|
|
18296
18414
|
* 显示帮助信息
|
|
18297
18415
|
*/
|
|
18298
|
-
showHelp() {
|
|
18299
|
-
|
|
18300
|
-
|
|
18301
|
-
|
|
18302
|
-
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18416
|
+
async showHelp(sessionService) {
|
|
18417
|
+
await this.output(
|
|
18418
|
+
sessionService,
|
|
18419
|
+
[
|
|
18420
|
+
"Agent Management Commands:",
|
|
18421
|
+
"",
|
|
18422
|
+
" /agent list - List all available agents",
|
|
18423
|
+
" /agent <name> <goal> - Delegate a task to an agent",
|
|
18424
|
+
"",
|
|
18425
|
+
"Examples:",
|
|
18426
|
+
" /agent list",
|
|
18427
|
+
' /agent explore "Find all TypeScript files"',
|
|
18428
|
+
' /agent general-purpose "Summarize current project status"'
|
|
18429
|
+
].join("\n")
|
|
18430
|
+
);
|
|
18308
18431
|
}
|
|
18309
18432
|
/**
|
|
18310
18433
|
* 列出所有 Agent
|
|
18311
18434
|
*/
|
|
18312
|
-
listAgents() {
|
|
18435
|
+
async listAgents(sessionService) {
|
|
18313
18436
|
const agents = this.agentManager.listAll();
|
|
18314
18437
|
if (agents.length === 0) {
|
|
18315
|
-
|
|
18438
|
+
await this.output(sessionService, "No agents available");
|
|
18316
18439
|
return;
|
|
18317
18440
|
}
|
|
18318
|
-
|
|
18319
|
-
\u{1F4CB} Available Agents (${agents.length}):
|
|
18320
|
-
`);
|
|
18441
|
+
const lines = [`\u{1F4CB} Available Agents (${agents.length}):`, ""];
|
|
18321
18442
|
for (const agent of agents) {
|
|
18322
|
-
|
|
18323
|
-
|
|
18443
|
+
lines.push(` \u{1F916} ${agent.name} (${agent.source})`);
|
|
18444
|
+
lines.push(` ${agent.description}`);
|
|
18324
18445
|
if (agent.tools) {
|
|
18325
|
-
|
|
18446
|
+
lines.push(` Tools: ${agent.tools.join(", ")}`);
|
|
18326
18447
|
}
|
|
18327
18448
|
if (agent.disallowedTools) {
|
|
18328
|
-
|
|
18449
|
+
lines.push(` Disallowed: ${agent.disallowedTools.join(", ")}`);
|
|
18329
18450
|
}
|
|
18330
18451
|
if (agent.model) {
|
|
18331
|
-
|
|
18452
|
+
lines.push(` Model: ${agent.model}`);
|
|
18332
18453
|
}
|
|
18333
18454
|
if (agent.forkContext) {
|
|
18334
|
-
|
|
18455
|
+
lines.push(` Fork Context: ${agent.forkContext}`);
|
|
18335
18456
|
}
|
|
18336
18457
|
if (agent.color) {
|
|
18337
|
-
|
|
18458
|
+
lines.push(` Color: ${agent.color}`);
|
|
18338
18459
|
}
|
|
18339
|
-
|
|
18460
|
+
lines.push("");
|
|
18340
18461
|
}
|
|
18462
|
+
await this.output(sessionService, lines.join("\n").trimEnd());
|
|
18341
18463
|
}
|
|
18342
18464
|
/**
|
|
18343
18465
|
* 委托任务给 Agent
|
|
18344
18466
|
*/
|
|
18345
|
-
async delegateTask(agentName, goal) {
|
|
18467
|
+
async delegateTask(agentName, goal, sessionService) {
|
|
18346
18468
|
if (!this.agentManager.has(agentName)) {
|
|
18347
|
-
|
|
18348
|
-
|
|
18469
|
+
await this.output(
|
|
18470
|
+
sessionService,
|
|
18471
|
+
`\u274C Agent not found: ${agentName}
|
|
18472
|
+
\u{1F4A1} Use /agent list to see available agents`
|
|
18473
|
+
);
|
|
18349
18474
|
return;
|
|
18350
18475
|
}
|
|
18351
18476
|
try {
|
|
18352
|
-
|
|
18353
|
-
|
|
18354
|
-
console.log(` Goal: ${goal}
|
|
18355
|
-
`);
|
|
18477
|
+
await this.output(sessionService, `\u{1F916} Delegating task to ${agentName}...
|
|
18478
|
+
Goal: ${goal}`);
|
|
18356
18479
|
const result = await this.agentManager.delegate(
|
|
18357
18480
|
{
|
|
18358
18481
|
type: "custom",
|
|
@@ -18361,25 +18484,40 @@ var AgentCommand = class extends SlashCommand {
|
|
|
18361
18484
|
agentName
|
|
18362
18485
|
);
|
|
18363
18486
|
if (result.success) {
|
|
18364
|
-
|
|
18365
|
-
\u2705 Task completed by ${agentName}`);
|
|
18487
|
+
let message = `\u2705 Task completed by ${agentName}`;
|
|
18366
18488
|
if (result.message) {
|
|
18367
|
-
|
|
18489
|
+
message += `
|
|
18490
|
+
${result.message}`;
|
|
18368
18491
|
}
|
|
18369
18492
|
if (result.data) {
|
|
18370
|
-
|
|
18493
|
+
message += `
|
|
18494
|
+
Data: ${JSON.stringify(result.data, null, 2)}`;
|
|
18371
18495
|
}
|
|
18496
|
+
await this.output(sessionService, message);
|
|
18372
18497
|
} else {
|
|
18373
|
-
|
|
18374
|
-
\u274C Task failed`);
|
|
18498
|
+
let message = "\u274C Task failed";
|
|
18375
18499
|
if (result.message) {
|
|
18376
|
-
|
|
18500
|
+
message += `
|
|
18501
|
+
${result.message}`;
|
|
18377
18502
|
}
|
|
18503
|
+
await this.output(sessionService, message);
|
|
18378
18504
|
}
|
|
18379
18505
|
} catch (error) {
|
|
18380
|
-
|
|
18381
|
-
|
|
18506
|
+
await this.output(
|
|
18507
|
+
sessionService,
|
|
18508
|
+
`\u274C Error: ${error instanceof Error ? error.message : String(error)}`
|
|
18509
|
+
);
|
|
18510
|
+
}
|
|
18511
|
+
}
|
|
18512
|
+
async output(sessionService, message) {
|
|
18513
|
+
if (sessionService) {
|
|
18514
|
+
await sessionService.addMessage({
|
|
18515
|
+
role: "assistant",
|
|
18516
|
+
content: message
|
|
18517
|
+
});
|
|
18518
|
+
return;
|
|
18382
18519
|
}
|
|
18520
|
+
console.log(message);
|
|
18383
18521
|
}
|
|
18384
18522
|
};
|
|
18385
18523
|
|
|
@@ -18397,53 +18535,83 @@ var CommitCommand = class extends SlashCommand {
|
|
|
18397
18535
|
this.modelService = modelService;
|
|
18398
18536
|
this.configManager = configManager;
|
|
18399
18537
|
}
|
|
18400
|
-
async execute(args) {
|
|
18538
|
+
async execute(args, app) {
|
|
18401
18539
|
const options = this.parseOptions(args);
|
|
18540
|
+
const sessionService = app.getContainer().get("session");
|
|
18402
18541
|
try {
|
|
18403
18542
|
if (options.stage) {
|
|
18404
|
-
|
|
18543
|
+
await this.output(sessionService, "\u{1F4E6} Staging all changes...");
|
|
18405
18544
|
this.execCommand("git add -A");
|
|
18406
18545
|
}
|
|
18407
|
-
|
|
18546
|
+
await this.output(sessionService, "\u{1F50D} Analyzing changes...");
|
|
18408
18547
|
const diff = await this.getDiff(true);
|
|
18409
18548
|
if (!diff || diff.trim().length === 0) {
|
|
18410
|
-
|
|
18549
|
+
await this.output(
|
|
18550
|
+
sessionService,
|
|
18551
|
+
"\u274C No staged changes to commit. Stage files first or run `/commit --stage`."
|
|
18552
|
+
);
|
|
18411
18553
|
return;
|
|
18412
18554
|
}
|
|
18413
18555
|
let commitHistory = "";
|
|
18414
18556
|
if (options.followStyle) {
|
|
18415
|
-
|
|
18557
|
+
await this.output(sessionService, "\u{1F4DA} Learning commit style from history...");
|
|
18416
18558
|
const history = await this.getCommitHistory(50);
|
|
18417
18559
|
commitHistory = history.join("\n");
|
|
18418
18560
|
}
|
|
18419
|
-
|
|
18561
|
+
await this.output(sessionService, "\u{1F916} Generating commit message...");
|
|
18420
18562
|
const commitMessage = await this.generateCommitMessage(diff, commitHistory, options);
|
|
18421
18563
|
if (options.copy) {
|
|
18422
18564
|
await this.copyToClipboard(commitMessage);
|
|
18423
|
-
|
|
18424
|
-
|
|
18565
|
+
await this.output(
|
|
18566
|
+
sessionService,
|
|
18567
|
+
`\u{1F4CB} Commit message copied to clipboard
|
|
18568
|
+
|
|
18569
|
+
${commitMessage}`
|
|
18570
|
+
);
|
|
18425
18571
|
return;
|
|
18426
18572
|
}
|
|
18427
|
-
console.log("\n\u{1F4DD} Generated commit message:\n");
|
|
18428
|
-
console.log(commitMessage);
|
|
18429
|
-
console.log("");
|
|
18430
18573
|
if (!options.commit) {
|
|
18431
|
-
|
|
18432
|
-
|
|
18433
|
-
|
|
18434
|
-
|
|
18435
|
-
|
|
18574
|
+
await this.output(
|
|
18575
|
+
sessionService,
|
|
18576
|
+
`\u{1F4DD} Generated commit message:
|
|
18577
|
+
|
|
18578
|
+
${commitMessage}
|
|
18579
|
+
|
|
18580
|
+
Use \`/commit --commit\` to create the commit, or \`/commit --copy\` to copy the message.`
|
|
18581
|
+
);
|
|
18582
|
+
return;
|
|
18436
18583
|
}
|
|
18584
|
+
await this.output(
|
|
18585
|
+
sessionService,
|
|
18586
|
+
`\u{1F4DD} Generated commit message:
|
|
18587
|
+
|
|
18588
|
+
${commitMessage}
|
|
18589
|
+
|
|
18590
|
+
\u{1F680} Creating commit...`
|
|
18591
|
+
);
|
|
18437
18592
|
await this.executeCommit(commitMessage, options);
|
|
18438
|
-
|
|
18593
|
+
await this.output(sessionService, "\u2705 Commit successful");
|
|
18439
18594
|
if (options.push) {
|
|
18440
|
-
|
|
18595
|
+
await this.output(sessionService, "\u{1F4E4} Pushing to remote...");
|
|
18441
18596
|
this.execCommand("git push");
|
|
18442
|
-
|
|
18597
|
+
await this.output(sessionService, "\u2705 Push successful");
|
|
18443
18598
|
}
|
|
18444
18599
|
} catch (error) {
|
|
18445
|
-
|
|
18600
|
+
await this.output(
|
|
18601
|
+
sessionService,
|
|
18602
|
+
`\u274C Error: ${error instanceof Error ? error.message : String(error)}`
|
|
18603
|
+
);
|
|
18604
|
+
}
|
|
18605
|
+
}
|
|
18606
|
+
async output(sessionService, message) {
|
|
18607
|
+
if (sessionService) {
|
|
18608
|
+
await sessionService.addMessage({
|
|
18609
|
+
role: "assistant",
|
|
18610
|
+
content: message
|
|
18611
|
+
});
|
|
18612
|
+
return;
|
|
18446
18613
|
}
|
|
18614
|
+
console.log(message);
|
|
18447
18615
|
}
|
|
18448
18616
|
/**
|
|
18449
18617
|
* 解析命令选项
|
|
@@ -18590,17 +18758,6 @@ Requirements:
|
|
|
18590
18758
|
|
|
18591
18759
|
Output only the commit message, no explanations.`;
|
|
18592
18760
|
}
|
|
18593
|
-
/**
|
|
18594
|
-
* 确认提交
|
|
18595
|
-
*/
|
|
18596
|
-
async confirmCommit() {
|
|
18597
|
-
console.log("Press Enter to commit, or Ctrl+C to cancel...");
|
|
18598
|
-
return new Promise((resolve11) => {
|
|
18599
|
-
process.stdin.once("data", () => {
|
|
18600
|
-
resolve11(true);
|
|
18601
|
-
});
|
|
18602
|
-
});
|
|
18603
|
-
}
|
|
18604
18761
|
/**
|
|
18605
18762
|
* 执行提交
|
|
18606
18763
|
*/
|
|
@@ -20916,13 +21073,73 @@ var ConfigService = class {
|
|
|
20916
21073
|
*/
|
|
20917
21074
|
getModelConfig() {
|
|
20918
21075
|
const config = this.getConfig();
|
|
21076
|
+
const legacyModel = typeof config.model === "object" ? config.model : void 0;
|
|
21077
|
+
const providerKey = this.getProviderKey(config) || "deepseek";
|
|
21078
|
+
const providerConfig = config.provider?.[providerKey];
|
|
21079
|
+
const envConfig = this.getProviderEnvConfig(providerKey);
|
|
20919
21080
|
return {
|
|
20920
|
-
apiKey:
|
|
20921
|
-
baseURL:
|
|
20922
|
-
model: config.model
|
|
20923
|
-
temperature: config.temperature
|
|
21081
|
+
apiKey: envConfig.apiKey || providerConfig?.apiKey || legacyModel?.apiKey || "",
|
|
21082
|
+
baseURL: envConfig.baseURL || providerConfig?.baseURL || legacyModel?.baseURL || this.getDefaultBaseURL(providerKey),
|
|
21083
|
+
model: (typeof config.model === "string" ? config.model : void 0) || legacyModel?.model || this.getDefaultModel(providerKey),
|
|
21084
|
+
temperature: config.temperature ?? legacyModel?.temperature ?? 0.7
|
|
20924
21085
|
};
|
|
20925
21086
|
}
|
|
21087
|
+
getProviderKey(config) {
|
|
21088
|
+
const metadataProvider = config._metadata?.provider;
|
|
21089
|
+
if (typeof metadataProvider === "string" && metadataProvider.trim()) {
|
|
21090
|
+
return metadataProvider;
|
|
21091
|
+
}
|
|
21092
|
+
const providerKeys = config.provider ? Object.keys(config.provider) : [];
|
|
21093
|
+
if (providerKeys.length === 1) {
|
|
21094
|
+
return providerKeys[0];
|
|
21095
|
+
}
|
|
21096
|
+
return void 0;
|
|
21097
|
+
}
|
|
21098
|
+
getDefaultModel(providerKey) {
|
|
21099
|
+
const defaults = {
|
|
21100
|
+
openai: "gpt-4",
|
|
21101
|
+
anthropic: "claude-3-5-sonnet-20241022",
|
|
21102
|
+
deepseek: "deepseek-chat",
|
|
21103
|
+
openrouter: "anthropic/claude-3.5-sonnet",
|
|
21104
|
+
custom: "gpt-4"
|
|
21105
|
+
};
|
|
21106
|
+
return defaults[providerKey] || "deepseek-chat";
|
|
21107
|
+
}
|
|
21108
|
+
getDefaultBaseURL(providerKey) {
|
|
21109
|
+
const defaults = {
|
|
21110
|
+
openai: "https://api.openai.com/v1",
|
|
21111
|
+
anthropic: "https://api.anthropic.com",
|
|
21112
|
+
deepseek: "https://api.deepseek.com",
|
|
21113
|
+
openrouter: "https://openrouter.ai/api/v1",
|
|
21114
|
+
custom: "https://api.openai.com/v1"
|
|
21115
|
+
};
|
|
21116
|
+
return defaults[providerKey] || "https://api.deepseek.com";
|
|
21117
|
+
}
|
|
21118
|
+
getProviderEnvConfig(providerKey) {
|
|
21119
|
+
const envMap = {
|
|
21120
|
+
openai: {
|
|
21121
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
21122
|
+
baseURL: process.env.OPENAI_BASE_URL
|
|
21123
|
+
},
|
|
21124
|
+
anthropic: {
|
|
21125
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
21126
|
+
baseURL: process.env.ANTHROPIC_BASE_URL
|
|
21127
|
+
},
|
|
21128
|
+
deepseek: {
|
|
21129
|
+
apiKey: process.env.DEEPSEEK_API_KEY,
|
|
21130
|
+
baseURL: process.env.DEEPSEEK_BASE_URL
|
|
21131
|
+
},
|
|
21132
|
+
openrouter: {
|
|
21133
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
21134
|
+
baseURL: process.env.OPENROUTER_BASE_URL
|
|
21135
|
+
},
|
|
21136
|
+
custom: {
|
|
21137
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
21138
|
+
baseURL: process.env.OPENAI_BASE_URL
|
|
21139
|
+
}
|
|
21140
|
+
};
|
|
21141
|
+
return envMap[providerKey] || {};
|
|
21142
|
+
}
|
|
20926
21143
|
/**
|
|
20927
21144
|
* 获取应用配置(向后兼容)
|
|
20928
21145
|
*/
|
|
@@ -21021,6 +21238,18 @@ function useSession() {
|
|
|
21021
21238
|
const { app, currentSession, setCurrentSession, setSessions } = useAppContext();
|
|
21022
21239
|
const sessionService = app.getContainer().get("session");
|
|
21023
21240
|
const eventBus = app.getContainer().get("eventBus");
|
|
21241
|
+
const syncCurrentSession = () => {
|
|
21242
|
+
const session = sessionService.getCurrent();
|
|
21243
|
+
if (!session) {
|
|
21244
|
+
return;
|
|
21245
|
+
}
|
|
21246
|
+
setCurrentSession({
|
|
21247
|
+
...session,
|
|
21248
|
+
messages: session.messages.slice(),
|
|
21249
|
+
config: session.config ? { ...session.config } : void 0
|
|
21250
|
+
});
|
|
21251
|
+
setSessions(sessionService.list());
|
|
21252
|
+
};
|
|
21024
21253
|
useEffect(() => {
|
|
21025
21254
|
const initSession = async () => {
|
|
21026
21255
|
try {
|
|
@@ -21060,11 +21289,31 @@ function useSession() {
|
|
|
21060
21289
|
const handleSessionLoaded = (data) => {
|
|
21061
21290
|
setCurrentSession(data.session);
|
|
21062
21291
|
};
|
|
21292
|
+
const handleMessageSent = () => {
|
|
21293
|
+
syncCurrentSession();
|
|
21294
|
+
};
|
|
21295
|
+
const handleSessionSaved = () => {
|
|
21296
|
+
syncCurrentSession();
|
|
21297
|
+
};
|
|
21298
|
+
const handleSessionUpdated = () => {
|
|
21299
|
+
syncCurrentSession();
|
|
21300
|
+
};
|
|
21301
|
+
const handleSessionResumed = () => {
|
|
21302
|
+
syncCurrentSession();
|
|
21303
|
+
};
|
|
21063
21304
|
eventBus.on("session.created" /* SESSION_CREATED */, handleSessionCreated);
|
|
21064
21305
|
eventBus.on("session.loaded" /* SESSION_LOADED */, handleSessionLoaded);
|
|
21306
|
+
eventBus.on("message.sent" /* MESSAGE_SENT */, handleMessageSent);
|
|
21307
|
+
eventBus.on("session.saved" /* SESSION_SAVED */, handleSessionSaved);
|
|
21308
|
+
eventBus.on("session_updated", handleSessionUpdated);
|
|
21309
|
+
eventBus.on("session:resumed", handleSessionResumed);
|
|
21065
21310
|
return () => {
|
|
21066
21311
|
eventBus.off("session.created" /* SESSION_CREATED */, handleSessionCreated);
|
|
21067
21312
|
eventBus.off("session.loaded" /* SESSION_LOADED */, handleSessionLoaded);
|
|
21313
|
+
eventBus.off("message.sent" /* MESSAGE_SENT */, handleMessageSent);
|
|
21314
|
+
eventBus.off("session.saved" /* SESSION_SAVED */, handleSessionSaved);
|
|
21315
|
+
eventBus.off("session_updated", handleSessionUpdated);
|
|
21316
|
+
eventBus.off("session:resumed", handleSessionResumed);
|
|
21068
21317
|
};
|
|
21069
21318
|
}, [sessionService, eventBus, setCurrentSession, setSessions]);
|
|
21070
21319
|
return {
|
|
@@ -21306,6 +21555,7 @@ var EnhancedMessageList = ({
|
|
|
21306
21555
|
|
|
21307
21556
|
// src/ui/components/SimpleInput.tsx
|
|
21308
21557
|
init_esm_shims();
|
|
21558
|
+
var MAX_VISIBLE_SUGGESTIONS = 8;
|
|
21309
21559
|
var SimpleSuggestionEngine = class {
|
|
21310
21560
|
commands = [
|
|
21311
21561
|
"/help",
|
|
@@ -21378,6 +21628,7 @@ var SimpleInput = ({
|
|
|
21378
21628
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
21379
21629
|
const [showSuggestions, setShowSuggestions] = useState(false);
|
|
21380
21630
|
const suggestionEngine = useRef(new SimpleSuggestionEngine());
|
|
21631
|
+
const submittedValueRef = useRef(null);
|
|
21381
21632
|
useEffect(() => {
|
|
21382
21633
|
if (input.startsWith("/")) {
|
|
21383
21634
|
const newSuggestions = suggestionEngine.current.getSuggestions(input);
|
|
@@ -21396,7 +21647,13 @@ var SimpleInput = ({
|
|
|
21396
21647
|
} else if (key.downArrow) {
|
|
21397
21648
|
setSelectedIndex((prev) => prev === suggestions.length - 1 ? 0 : prev + 1);
|
|
21398
21649
|
} else if (key.return && suggestions[selectedIndex]) {
|
|
21399
|
-
|
|
21650
|
+
const selectedSuggestion = suggestions[selectedIndex].text;
|
|
21651
|
+
if (input !== selectedSuggestion) {
|
|
21652
|
+
setInput(selectedSuggestion);
|
|
21653
|
+
} else if (submittedValueRef.current === selectedSuggestion) {
|
|
21654
|
+
setInput("");
|
|
21655
|
+
submittedValueRef.current = null;
|
|
21656
|
+
}
|
|
21400
21657
|
setShowSuggestions(false);
|
|
21401
21658
|
} else if (key.escape) {
|
|
21402
21659
|
setShowSuggestions(false);
|
|
@@ -21408,6 +21665,7 @@ var SimpleInput = ({
|
|
|
21408
21665
|
const handleSubmit = useCallback(
|
|
21409
21666
|
(value) => {
|
|
21410
21667
|
if (!value.trim() || disabled) return;
|
|
21668
|
+
submittedValueRef.current = value;
|
|
21411
21669
|
setInput("");
|
|
21412
21670
|
setShowSuggestions(false);
|
|
21413
21671
|
onSubmit(value);
|
|
@@ -21416,6 +21674,16 @@ var SimpleInput = ({
|
|
|
21416
21674
|
);
|
|
21417
21675
|
const promptSymbol = ">";
|
|
21418
21676
|
const promptColor = input.startsWith("/") ? "blue" : "green";
|
|
21677
|
+
const visibleSuggestions = showSuggestions && suggestions.length > 0 ? Array.from(
|
|
21678
|
+
{ length: Math.min(MAX_VISIBLE_SUGGESTIONS, suggestions.length) },
|
|
21679
|
+
(_, offset) => {
|
|
21680
|
+
const index = (selectedIndex + offset) % suggestions.length;
|
|
21681
|
+
return {
|
|
21682
|
+
suggestion: suggestions[index],
|
|
21683
|
+
index
|
|
21684
|
+
};
|
|
21685
|
+
}
|
|
21686
|
+
) : [];
|
|
21419
21687
|
const getStatusIndicator = () => {
|
|
21420
21688
|
switch (status) {
|
|
21421
21689
|
case "thinking":
|
|
@@ -21428,7 +21696,7 @@ var SimpleInput = ({
|
|
|
21428
21696
|
return "";
|
|
21429
21697
|
}
|
|
21430
21698
|
};
|
|
21431
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, status !== "idle" && /* @__PURE__ */ React.createElement(Box, { marginBottom: 1, paddingX: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, getStatusIndicator())), !disabled && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { paddingX: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "gray" }, "\u2500".repeat(80))), /* @__PURE__ */ React.createElement(Box, { paddingX: 2
|
|
21699
|
+
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, status !== "idle" && /* @__PURE__ */ React.createElement(Box, { marginBottom: 1, paddingX: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "yellow" }, getStatusIndicator())), input.length === 0 && !showSuggestions && /* @__PURE__ */ React.createElement(Box, { paddingX: 2, marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "gray", dimColor: true }, "Type / for commands \u2022 Enter to send")), !disabled && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { paddingX: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "gray" }, "\u2500".repeat(80))), /* @__PURE__ */ React.createElement(Box, { paddingX: 2 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row", alignItems: "center" }, /* @__PURE__ */ React.createElement(Text, { color: promptColor, bold: true }, promptSymbol, " "), /* @__PURE__ */ React.createElement(
|
|
21432
21700
|
TextInput,
|
|
21433
21701
|
{
|
|
21434
21702
|
value: input,
|
|
@@ -21436,21 +21704,22 @@ var SimpleInput = ({
|
|
|
21436
21704
|
onSubmit: handleSubmit,
|
|
21437
21705
|
placeholder
|
|
21438
21706
|
}
|
|
21439
|
-
))), /* @__PURE__ */ React.createElement(Box, { paddingX: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "gray" }, "\u2500".repeat(80)))), showSuggestions && suggestions.length > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingX: 2, marginTop: 1 },
|
|
21707
|
+
))), /* @__PURE__ */ React.createElement(Box, { paddingX: 2 }, /* @__PURE__ */ React.createElement(Text, { color: "gray" }, "\u2500".repeat(80)))), showSuggestions && suggestions.length > 0 && /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingX: 2, marginTop: 1 }, visibleSuggestions.map(({ suggestion, index }) => /* @__PURE__ */ React.createElement(Box, { key: `${suggestion.text}-${index}`, flexDirection: "row", width: "100%" }, /* @__PURE__ */ React.createElement(Box, { width: 20, flexShrink: 0 }, /* @__PURE__ */ React.createElement(
|
|
21440
21708
|
Text,
|
|
21441
21709
|
{
|
|
21442
21710
|
color: index === selectedIndex ? "cyan" : "gray",
|
|
21443
21711
|
bold: index === selectedIndex
|
|
21444
21712
|
},
|
|
21445
21713
|
suggestion.text
|
|
21446
|
-
)), /* @__PURE__ */ React.createElement(
|
|
21714
|
+
)), /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }, /* @__PURE__ */ React.createElement(
|
|
21447
21715
|
Text,
|
|
21448
21716
|
{
|
|
21449
21717
|
color: index === selectedIndex ? "white" : "dim",
|
|
21450
|
-
dimColor: index !== selectedIndex
|
|
21718
|
+
dimColor: index !== selectedIndex,
|
|
21719
|
+
wrap: "truncate-end"
|
|
21451
21720
|
},
|
|
21452
21721
|
suggestion.description
|
|
21453
|
-
))), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "gray", dimColor: true }, "\u2191\u2193 navigate \u2022 Enter/Tab select \u2022 Esc cancel")))
|
|
21722
|
+
)))), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "gray", dimColor: true }, "\u2191\u2193 navigate \u2022 Enter/Tab select \u2022 Esc cancel"))));
|
|
21454
21723
|
};
|
|
21455
21724
|
|
|
21456
21725
|
// src/ui/components/WelcomeScreen.tsx
|
|
@@ -21976,6 +22245,20 @@ function AppContent() {
|
|
|
21976
22245
|
const [showResumeSelector, setShowResumeSelector] = useState(false);
|
|
21977
22246
|
const [showMcpManager, setShowMcpManager] = useState(false);
|
|
21978
22247
|
const [showStatusManager, setShowStatusManager] = useState(false);
|
|
22248
|
+
const resetTransientUi = useCallback(() => {
|
|
22249
|
+
setShowModelSelector(false);
|
|
22250
|
+
setShowRewindSelector(false);
|
|
22251
|
+
setShowResumeSelector(false);
|
|
22252
|
+
setShowMcpManager(false);
|
|
22253
|
+
setShowStatusManager(false);
|
|
22254
|
+
}, []);
|
|
22255
|
+
const requestAppExit = useCallback(async () => {
|
|
22256
|
+
try {
|
|
22257
|
+
await app.stop();
|
|
22258
|
+
} finally {
|
|
22259
|
+
exit();
|
|
22260
|
+
}
|
|
22261
|
+
}, [app, exit]);
|
|
21979
22262
|
const messagesRef = useRef([]);
|
|
21980
22263
|
const [, forceUpdate] = useState({});
|
|
21981
22264
|
const historyMessages = messagesRef.current;
|
|
@@ -22099,6 +22382,16 @@ function AppContent() {
|
|
|
22099
22382
|
useInput(
|
|
22100
22383
|
useCallback(
|
|
22101
22384
|
(input, key) => {
|
|
22385
|
+
if (key.ctrl && input === "c") {
|
|
22386
|
+
if (transcriptMode) {
|
|
22387
|
+
clearTerminal();
|
|
22388
|
+
toggleTranscriptMode();
|
|
22389
|
+
refresh();
|
|
22390
|
+
} else {
|
|
22391
|
+
resetTransientUi();
|
|
22392
|
+
}
|
|
22393
|
+
return;
|
|
22394
|
+
}
|
|
22102
22395
|
if (key.ctrl && input === "o") {
|
|
22103
22396
|
clearTerminal();
|
|
22104
22397
|
toggleTranscriptMode();
|
|
@@ -22106,7 +22399,7 @@ function AppContent() {
|
|
|
22106
22399
|
return;
|
|
22107
22400
|
}
|
|
22108
22401
|
if (transcriptMode) {
|
|
22109
|
-
if (key.escape
|
|
22402
|
+
if (key.escape) {
|
|
22110
22403
|
clearTerminal();
|
|
22111
22404
|
toggleTranscriptMode();
|
|
22112
22405
|
refresh();
|
|
@@ -22117,7 +22410,17 @@ function AppContent() {
|
|
|
22117
22410
|
return;
|
|
22118
22411
|
}
|
|
22119
22412
|
},
|
|
22120
|
-
[
|
|
22413
|
+
[
|
|
22414
|
+
transcriptMode,
|
|
22415
|
+
toggleTranscriptMode,
|
|
22416
|
+
refresh,
|
|
22417
|
+
showModelSelector,
|
|
22418
|
+
showRewindSelector,
|
|
22419
|
+
showResumeSelector,
|
|
22420
|
+
showMcpManager,
|
|
22421
|
+
showStatusManager,
|
|
22422
|
+
resetTransientUi
|
|
22423
|
+
]
|
|
22121
22424
|
)
|
|
22122
22425
|
);
|
|
22123
22426
|
const handleSubmit = useCallback(
|
|
@@ -22131,7 +22434,7 @@ function AppContent() {
|
|
|
22131
22434
|
return;
|
|
22132
22435
|
}
|
|
22133
22436
|
if (value.trim().toLowerCase() === "exit" || value.trim().toLowerCase() === "quit") {
|
|
22134
|
-
|
|
22437
|
+
await requestAppExit();
|
|
22135
22438
|
return;
|
|
22136
22439
|
}
|
|
22137
22440
|
setTasks([]);
|
|
@@ -22171,7 +22474,7 @@ function AppContent() {
|
|
|
22171
22474
|
setIsLoading(false);
|
|
22172
22475
|
}
|
|
22173
22476
|
},
|
|
22174
|
-
[currentSession, app, sessionService,
|
|
22477
|
+
[currentSession, app, sessionService, requestAppExit]
|
|
22175
22478
|
);
|
|
22176
22479
|
const handleModelSelect = useCallback(
|
|
22177
22480
|
async (modelId) => {
|
|
@@ -22182,11 +22485,20 @@ function AppContent() {
|
|
|
22182
22485
|
try {
|
|
22183
22486
|
modelService.updateConfig({ model: modelId });
|
|
22184
22487
|
setCurrentModelId(modelId);
|
|
22488
|
+
let missingApiKey = false;
|
|
22489
|
+
let configPath = "~/.codemate/config.json";
|
|
22185
22490
|
try {
|
|
22186
22491
|
const configService = app.getContainer().get("config");
|
|
22187
22492
|
if (configService && typeof configService.setConfig === "function") {
|
|
22188
22493
|
configService.setConfig(false, "model", modelId);
|
|
22189
22494
|
}
|
|
22495
|
+
if (configService && typeof configService.getGlobalConfigPath === "function") {
|
|
22496
|
+
configPath = configService.getGlobalConfigPath();
|
|
22497
|
+
}
|
|
22498
|
+
if (configService && typeof configService.getModelConfig === "function") {
|
|
22499
|
+
const modelConfig = configService.getModelConfig();
|
|
22500
|
+
missingApiKey = !modelConfig.apiKey;
|
|
22501
|
+
}
|
|
22190
22502
|
} catch (error) {
|
|
22191
22503
|
console.log("ConfigService not available, model change is temporary");
|
|
22192
22504
|
}
|
|
@@ -22194,7 +22506,7 @@ function AppContent() {
|
|
|
22194
22506
|
role: "assistant",
|
|
22195
22507
|
content: `\u2705 Model changed to ${modelId}
|
|
22196
22508
|
|
|
22197
|
-
\u{1F504} The model has been updated for this session. To make this change permanent, update your .
|
|
22509
|
+
\u{1F504} The model has been updated for this session. To make this change permanent, update your ${configPath} configuration file.${missingApiKey ? "\n\n\u26A0\uFE0F No API key configured. Run `codemate config` or set the provider API key in the config file to use this model." : ""}`
|
|
22198
22510
|
});
|
|
22199
22511
|
const eventBus = app.getContainer().get("eventBus");
|
|
22200
22512
|
eventBus.emit("model_changed", { newModel: modelId, previousModel: previousModelId });
|
|
@@ -22285,6 +22597,16 @@ function AppContent() {
|
|
|
22285
22597
|
eventBus.off("show_model_selector", handleShowModelSelector);
|
|
22286
22598
|
};
|
|
22287
22599
|
}, [app]);
|
|
22600
|
+
useEffect(() => {
|
|
22601
|
+
const eventBus = app.getContainer().get("eventBus");
|
|
22602
|
+
const handleExitApp = () => {
|
|
22603
|
+
void requestAppExit();
|
|
22604
|
+
};
|
|
22605
|
+
eventBus.on("exit_app", handleExitApp);
|
|
22606
|
+
return () => {
|
|
22607
|
+
eventBus.off("exit_app", handleExitApp);
|
|
22608
|
+
};
|
|
22609
|
+
}, [app, requestAppExit]);
|
|
22288
22610
|
useEffect(() => {
|
|
22289
22611
|
const eventBus = app.getContainer().get("eventBus");
|
|
22290
22612
|
const handleShowRewindSelector = () => {
|
|
@@ -22460,10 +22782,13 @@ function App({ app }) {
|
|
|
22460
22782
|
// src/utils/firstRun.ts
|
|
22461
22783
|
init_esm_shims();
|
|
22462
22784
|
function isFirstRun() {
|
|
22463
|
-
|
|
22464
|
-
return !fs21__default.existsSync(configPath);
|
|
22785
|
+
return !fs21__default.existsSync(getConfigPath()) && !fs21__default.existsSync(getLegacyConfigPath());
|
|
22465
22786
|
}
|
|
22466
22787
|
function getConfigPath() {
|
|
22788
|
+
const homeDir = os4__default.homedir();
|
|
22789
|
+
return path18.join(homeDir, ".codemate", "config.json");
|
|
22790
|
+
}
|
|
22791
|
+
function getLegacyConfigPath() {
|
|
22467
22792
|
const homeDir = os4__default.homedir();
|
|
22468
22793
|
return path18.join(homeDir, ".aiclirc.json");
|
|
22469
22794
|
}
|
|
@@ -22489,12 +22814,14 @@ function createDefaultConfig(apiKey, provider, model, baseURL) {
|
|
|
22489
22814
|
logLevel: "info",
|
|
22490
22815
|
workDir: process.cwd()
|
|
22491
22816
|
},
|
|
22492
|
-
model:
|
|
22493
|
-
|
|
22494
|
-
|
|
22495
|
-
|
|
22496
|
-
|
|
22817
|
+
model: model || defaultModels[provider] || "gpt-4",
|
|
22818
|
+
provider: {
|
|
22819
|
+
[provider]: {
|
|
22820
|
+
apiKey,
|
|
22821
|
+
baseURL: baseURL || defaultBaseURLs[provider] || "https://api.openai.com/v1"
|
|
22822
|
+
}
|
|
22497
22823
|
},
|
|
22824
|
+
temperature: 0.7,
|
|
22498
22825
|
tools: {
|
|
22499
22826
|
enabled: [
|
|
22500
22827
|
"read_file",
|
|
@@ -22528,6 +22855,7 @@ function createDefaultConfig(apiKey, provider, model, baseURL) {
|
|
|
22528
22855
|
}
|
|
22529
22856
|
};
|
|
22530
22857
|
const configPath = getConfigPath();
|
|
22858
|
+
fs21__default.mkdirSync(path18.dirname(configPath), { recursive: true });
|
|
22531
22859
|
fs21__default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
22532
22860
|
}
|
|
22533
22861
|
|
|
@@ -22588,7 +22916,7 @@ async function runFirstTimeSetup() {
|
|
|
22588
22916
|
rl.close();
|
|
22589
22917
|
createDefaultConfig(apiKey.trim(), providerKey, model, baseURL || PROVIDERS[providerKey].baseURL);
|
|
22590
22918
|
console.log("");
|
|
22591
|
-
console.log("\u2705 \u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230: ~/.
|
|
22919
|
+
console.log("\u2705 \u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230: ~/.codemate/config.json");
|
|
22592
22920
|
console.log("");
|
|
22593
22921
|
console.log(`\u63D0\u4F9B\u5546: ${PROVIDERS[providerKey].name}`);
|
|
22594
22922
|
console.log(`\u6A21\u578B: ${model}`);
|
|
@@ -22646,7 +22974,9 @@ program.command("chat", { isDefault: true }).description("Start interactive chat
|
|
|
22646
22974
|
await sessionService.initialize();
|
|
22647
22975
|
console.log("\u2705 SessionService initialized");
|
|
22648
22976
|
console.log("\n\u{1F3A8} Starting interactive UI...\n");
|
|
22649
|
-
render(React.createElement(App, { app }));
|
|
22977
|
+
const inkApp = render(React.createElement(App, { app }));
|
|
22978
|
+
await inkApp.waitUntilExit();
|
|
22979
|
+
process.exit(0);
|
|
22650
22980
|
} catch (error) {
|
|
22651
22981
|
console.error("\u274C Fatal error:", error);
|
|
22652
22982
|
process.exit(1);
|
|
@@ -22656,7 +22986,7 @@ program.command("config").description("Configure or reconfigure CodeMate AI").ac
|
|
|
22656
22986
|
try {
|
|
22657
22987
|
console.log("\n\u{1F527} CodeMate AI \u914D\u7F6E\u5411\u5BFC\n");
|
|
22658
22988
|
if (!isFirstRun()) {
|
|
22659
|
-
console.log("\u5F53\u524D\u914D\u7F6E\u6587\u4EF6: ~/.
|
|
22989
|
+
console.log("\u5F53\u524D\u914D\u7F6E\u6587\u4EF6: ~/.codemate/config.json");
|
|
22660
22990
|
console.log("\u6B64\u64CD\u4F5C\u5C06\u8986\u76D6\u73B0\u6709\u914D\u7F6E\u3002\n");
|
|
22661
22991
|
}
|
|
22662
22992
|
await runFirstTimeSetup();
|