codemate-ai 1.0.7 → 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 +411 -181
- 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';
|
|
@@ -739,36 +739,43 @@ var init_WorkspaceCommand = __esm({
|
|
|
739
739
|
super();
|
|
740
740
|
this.configManager = configManager;
|
|
741
741
|
}
|
|
742
|
-
async execute(args) {
|
|
742
|
+
async execute(args, app) {
|
|
743
743
|
const subcommand = args[0];
|
|
744
|
+
const sessionService = app.getContainer().get("session");
|
|
744
745
|
try {
|
|
745
746
|
switch (subcommand) {
|
|
746
747
|
case "create":
|
|
747
|
-
await this.create(this.parseCreateOptions(args.slice(1)));
|
|
748
|
+
await this.create(this.parseCreateOptions(args.slice(1)), sessionService);
|
|
748
749
|
break;
|
|
749
750
|
case "list":
|
|
750
|
-
await this.list();
|
|
751
|
+
await this.list(sessionService);
|
|
751
752
|
break;
|
|
752
753
|
case "remove":
|
|
753
754
|
case "delete":
|
|
754
|
-
await this.remove(args[1]);
|
|
755
|
+
await this.remove(args[1], sessionService);
|
|
755
756
|
break;
|
|
756
757
|
case "complete":
|
|
757
|
-
await this.complete();
|
|
758
|
+
await this.complete(sessionService);
|
|
758
759
|
break;
|
|
759
760
|
default:
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
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")
|
|
768
772
|
);
|
|
769
773
|
}
|
|
770
774
|
} catch (error) {
|
|
771
|
-
|
|
775
|
+
await this.output(
|
|
776
|
+
sessionService,
|
|
777
|
+
`\u274C Error: ${error instanceof Error ? error.message : String(error)}`
|
|
778
|
+
);
|
|
772
779
|
}
|
|
773
780
|
}
|
|
774
781
|
/**
|
|
@@ -796,110 +803,121 @@ var init_WorkspaceCommand = __esm({
|
|
|
796
803
|
/**
|
|
797
804
|
* 创建工作区
|
|
798
805
|
*/
|
|
799
|
-
async create(options) {
|
|
806
|
+
async create(options, sessionService) {
|
|
800
807
|
const workspaceName = options.name;
|
|
801
808
|
if (!workspaceName) {
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
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
|
+
);
|
|
808
820
|
return;
|
|
809
821
|
}
|
|
810
822
|
const config = this.configManager.config;
|
|
811
823
|
const baseBranch = options.baseBranch || config.workspace?.baseBranch || "main";
|
|
812
824
|
if (!this.branchExists(baseBranch)) {
|
|
813
|
-
|
|
814
|
-
|
|
825
|
+
let message = `\u274C Base branch '${baseBranch}' does not exist
|
|
826
|
+
Available branches:`;
|
|
815
827
|
try {
|
|
816
828
|
const branches = this.execGit("branch -a").split("\n").map(
|
|
817
829
|
(line) => line.trim().replace(/^\*\s*/, "").replace(/^remotes\/origin\//, "")
|
|
818
830
|
).filter((line) => line && !line.includes("HEAD")).slice(0, 5);
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
}
|
|
831
|
+
message += `
|
|
832
|
+
${branches.map((branch) => ` - ${branch}`).join("\n")}`;
|
|
822
833
|
} catch {
|
|
823
|
-
|
|
834
|
+
message += "\n (Unable to list branches)";
|
|
824
835
|
}
|
|
836
|
+
await this.output(sessionService, message);
|
|
825
837
|
return;
|
|
826
838
|
}
|
|
827
839
|
const workspacePath = this.getWorkspacePath(workspaceName);
|
|
828
840
|
if (existsSync(workspacePath)) {
|
|
829
|
-
|
|
841
|
+
await this.output(sessionService, `\u274C Workspace already exists: ${workspacePath}`);
|
|
830
842
|
return;
|
|
831
843
|
}
|
|
832
844
|
const branchExists = this.branchExists(workspaceName);
|
|
833
|
-
|
|
845
|
+
await this.output(sessionService, `\u{1F33F} Creating workspace '${workspaceName}'...`);
|
|
834
846
|
try {
|
|
835
847
|
if (branchExists && !options.newBranch) {
|
|
836
848
|
this.execGit(`worktree add ${workspacePath} ${workspaceName}`);
|
|
837
849
|
} else {
|
|
838
850
|
this.execGit(`worktree add -b ${workspaceName} ${workspacePath} ${baseBranch}`);
|
|
839
851
|
}
|
|
840
|
-
|
|
841
|
-
|
|
852
|
+
await this.output(
|
|
853
|
+
sessionService,
|
|
854
|
+
`\u2705 Workspace created at: ${workspacePath}
|
|
855
|
+
\u{1F4A1} To start working: cd ${workspacePath}`
|
|
856
|
+
);
|
|
842
857
|
} catch (error) {
|
|
843
|
-
|
|
858
|
+
await this.output(sessionService, "\u274C Failed to create workspace");
|
|
844
859
|
throw error;
|
|
845
860
|
}
|
|
846
861
|
}
|
|
847
862
|
/**
|
|
848
863
|
* 列出所有工作区
|
|
849
864
|
*/
|
|
850
|
-
async list() {
|
|
865
|
+
async list(sessionService) {
|
|
851
866
|
try {
|
|
852
867
|
const output = this.execGit("worktree list --porcelain");
|
|
853
868
|
const workspaces = this.parseWorktreeList(output);
|
|
854
869
|
if (workspaces.length === 0) {
|
|
855
|
-
|
|
870
|
+
await this.output(sessionService, "\u{1F4CB} No workspaces found");
|
|
856
871
|
return;
|
|
857
872
|
}
|
|
858
|
-
|
|
873
|
+
const lines = ["\u{1F4CB} Workspaces:", ""];
|
|
859
874
|
for (const workspace of workspaces) {
|
|
860
875
|
const marker = workspace.isCurrent ? "\u2192" : " ";
|
|
861
876
|
const name = basename(workspace.path);
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
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("");
|
|
867
882
|
}
|
|
883
|
+
await this.output(sessionService, lines.join("\n").trimEnd());
|
|
868
884
|
} catch (error) {
|
|
869
|
-
|
|
885
|
+
await this.output(sessionService, "\u274C Failed to list workspaces");
|
|
870
886
|
throw error;
|
|
871
887
|
}
|
|
872
888
|
}
|
|
873
889
|
/**
|
|
874
890
|
* 删除工作区
|
|
875
891
|
*/
|
|
876
|
-
async remove(name) {
|
|
892
|
+
async remove(name, sessionService) {
|
|
877
893
|
if (!name) {
|
|
878
|
-
|
|
879
|
-
|
|
894
|
+
await this.output(
|
|
895
|
+
sessionService,
|
|
896
|
+
"\u274C Workspace name is required\nUsage: /workspace remove <name>"
|
|
897
|
+
);
|
|
880
898
|
return;
|
|
881
899
|
}
|
|
882
900
|
const workspacePath = this.getWorkspacePath(name);
|
|
883
901
|
if (!existsSync(workspacePath)) {
|
|
884
|
-
|
|
902
|
+
await this.output(sessionService, `\u274C Workspace not found: ${workspacePath}`);
|
|
885
903
|
return;
|
|
886
904
|
}
|
|
887
|
-
|
|
905
|
+
await this.output(sessionService, `\u{1F5D1}\uFE0F Removing workspace '${name}'...`);
|
|
888
906
|
try {
|
|
889
907
|
this.execGit(`worktree remove ${workspacePath}`);
|
|
890
|
-
|
|
908
|
+
await this.output(sessionService, `\u2705 Workspace removed: ${workspacePath}`);
|
|
891
909
|
} catch (error) {
|
|
892
|
-
|
|
910
|
+
await this.output(sessionService, "\u274C Failed to remove workspace");
|
|
893
911
|
throw error;
|
|
894
912
|
}
|
|
895
913
|
}
|
|
896
914
|
/**
|
|
897
915
|
* 完成并合并工作区
|
|
898
916
|
*/
|
|
899
|
-
async complete() {
|
|
917
|
+
async complete(sessionService) {
|
|
900
918
|
const currentBranch = this.getCurrentBranch();
|
|
901
919
|
if (!currentBranch) {
|
|
902
|
-
|
|
920
|
+
await this.output(sessionService, "\u274C Not in a Git repository");
|
|
903
921
|
return;
|
|
904
922
|
}
|
|
905
923
|
const config = this.configManager.config;
|
|
@@ -908,28 +926,41 @@ var init_WorkspaceCommand = __esm({
|
|
|
908
926
|
try {
|
|
909
927
|
this.execGit("diff-index --quiet HEAD --");
|
|
910
928
|
} catch {
|
|
911
|
-
|
|
929
|
+
await this.output(
|
|
930
|
+
sessionService,
|
|
931
|
+
"\u274C You have uncommitted changes. Please commit or stash them first."
|
|
932
|
+
);
|
|
912
933
|
return;
|
|
913
934
|
}
|
|
914
|
-
|
|
935
|
+
await this.output(sessionService, `\u{1F500} Merging ${currentBranch} into ${baseBranch}...`);
|
|
915
936
|
try {
|
|
916
937
|
this.execGit(`checkout ${baseBranch}`);
|
|
917
938
|
this.execGit(`merge ${currentBranch}`);
|
|
918
|
-
|
|
939
|
+
await this.output(sessionService, `\u2705 Merged ${currentBranch} into ${baseBranch}`);
|
|
919
940
|
const workspacePath = process.cwd();
|
|
920
|
-
|
|
941
|
+
await this.output(sessionService, "\u{1F5D1}\uFE0F Removing workspace...");
|
|
921
942
|
process.chdir("..");
|
|
922
943
|
this.execGit(`worktree remove ${workspacePath}`);
|
|
923
944
|
if (autoDelete) {
|
|
924
|
-
|
|
945
|
+
await this.output(sessionService, `\u{1F5D1}\uFE0F Deleting branch ${currentBranch}...`);
|
|
925
946
|
this.execGit(`branch -d ${currentBranch}`);
|
|
926
947
|
}
|
|
927
|
-
|
|
948
|
+
await this.output(sessionService, "\u2705 Workspace completed and merged!");
|
|
928
949
|
} catch (error) {
|
|
929
|
-
|
|
950
|
+
await this.output(sessionService, "\u274C Failed to complete workspace");
|
|
930
951
|
throw error;
|
|
931
952
|
}
|
|
932
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
|
+
}
|
|
933
964
|
/**
|
|
934
965
|
* 获取项目名称
|
|
935
966
|
*/
|
|
@@ -8705,7 +8736,6 @@ var SessionService = class {
|
|
|
8705
8736
|
}
|
|
8706
8737
|
/**
|
|
8707
8738
|
* 清除当前会话并创建新会话
|
|
8708
|
-
* 对标Neovate的clear命令功能
|
|
8709
8739
|
*/
|
|
8710
8740
|
async clear() {
|
|
8711
8741
|
const newSession = await this.create();
|
|
@@ -9529,6 +9559,11 @@ var ExitCommand = class extends SlashCommand {
|
|
|
9529
9559
|
description = "Exit the program";
|
|
9530
9560
|
aliases = ["quit", "q"];
|
|
9531
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
|
+
}
|
|
9532
9567
|
console.log("\u{1F44B} Goodbye!");
|
|
9533
9568
|
await app.stop();
|
|
9534
9569
|
process.exit(0);
|
|
@@ -9647,8 +9682,9 @@ var ConfigCommand = class extends SlashCommand {
|
|
|
9647
9682
|
*/
|
|
9648
9683
|
async execute(args, app) {
|
|
9649
9684
|
const configService = app.getContainer().get("config");
|
|
9685
|
+
const sessionService = app.getContainer().get("session");
|
|
9650
9686
|
if (!configService) {
|
|
9651
|
-
|
|
9687
|
+
await this.outputResult(sessionService, "\u274C ConfigService not available");
|
|
9652
9688
|
return;
|
|
9653
9689
|
}
|
|
9654
9690
|
const [action, ...rest] = args;
|
|
@@ -9672,6 +9708,16 @@ var ConfigCommand = class extends SlashCommand {
|
|
|
9672
9708
|
default:
|
|
9673
9709
|
result = this.getHelp();
|
|
9674
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
|
+
}
|
|
9675
9721
|
console.log(result);
|
|
9676
9722
|
}
|
|
9677
9723
|
/**
|
|
@@ -9834,17 +9880,17 @@ var ForkCommand = class extends SlashCommand {
|
|
|
9834
9880
|
async execute(args, app) {
|
|
9835
9881
|
const sessionService = app.getContainer().get("session");
|
|
9836
9882
|
if (!sessionService) {
|
|
9837
|
-
|
|
9883
|
+
await this.output(void 0, "\u274C SessionService not available");
|
|
9838
9884
|
return;
|
|
9839
9885
|
}
|
|
9840
9886
|
const currentSession = sessionService.getCurrent();
|
|
9841
9887
|
if (!currentSession) {
|
|
9842
|
-
|
|
9888
|
+
await this.output(sessionService, "\u274C No active session");
|
|
9843
9889
|
return;
|
|
9844
9890
|
}
|
|
9845
9891
|
const messages = currentSession.messages;
|
|
9846
9892
|
if (messages.length === 0) {
|
|
9847
|
-
|
|
9893
|
+
await this.output(sessionService, "\u274C No messages to fork from");
|
|
9848
9894
|
return;
|
|
9849
9895
|
}
|
|
9850
9896
|
if (args.length > 0) {
|
|
@@ -9852,7 +9898,7 @@ var ForkCommand = class extends SlashCommand {
|
|
|
9852
9898
|
await this.forkFromMessage(sessionService, messageUuid);
|
|
9853
9899
|
return;
|
|
9854
9900
|
}
|
|
9855
|
-
this.showForkSelector(messages);
|
|
9901
|
+
await this.showForkSelector(sessionService, messages);
|
|
9856
9902
|
}
|
|
9857
9903
|
/**
|
|
9858
9904
|
* 从指定消息分叉
|
|
@@ -9862,27 +9908,36 @@ var ForkCommand = class extends SlashCommand {
|
|
|
9862
9908
|
const newSession = await sessionService.fork({
|
|
9863
9909
|
fromMessageUuid: messageUuid
|
|
9864
9910
|
});
|
|
9865
|
-
|
|
9866
|
-
|
|
9911
|
+
await this.output(
|
|
9912
|
+
sessionService,
|
|
9913
|
+
`\u2705 Session forked: ${newSession.id}
|
|
9914
|
+
Use /sessions to switch to it.`
|
|
9915
|
+
);
|
|
9867
9916
|
} catch (error) {
|
|
9868
|
-
|
|
9917
|
+
await this.output(
|
|
9918
|
+
sessionService,
|
|
9919
|
+
`\u274C Fork failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
9920
|
+
);
|
|
9869
9921
|
}
|
|
9870
9922
|
}
|
|
9871
9923
|
/**
|
|
9872
9924
|
* 显示分叉选择器
|
|
9873
9925
|
*/
|
|
9874
|
-
showForkSelector(messages) {
|
|
9926
|
+
async showForkSelector(sessionService, messages) {
|
|
9875
9927
|
const messagesWithUuid = messages.filter((msg) => msg.uuid);
|
|
9876
9928
|
if (messagesWithUuid.length === 0) {
|
|
9877
|
-
|
|
9878
|
-
|
|
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
|
+
);
|
|
9879
9933
|
return;
|
|
9880
9934
|
}
|
|
9881
9935
|
const messageList = messagesWithUuid.map((msg, index) => {
|
|
9882
9936
|
const preview = this.getMessagePreview(msg);
|
|
9883
9937
|
return `${index + 1}. [${msg.uuid.slice(0, 8)}] ${msg.role}: ${preview}`;
|
|
9884
9938
|
}).join("\n");
|
|
9885
|
-
|
|
9939
|
+
await this.output(
|
|
9940
|
+
sessionService,
|
|
9886
9941
|
`
|
|
9887
9942
|
\u{1F4CB} Select a message to fork from:
|
|
9888
9943
|
|
|
@@ -9894,6 +9949,16 @@ Example: /fork ${messagesWithUuid[0].uuid}
|
|
|
9894
9949
|
`.trim()
|
|
9895
9950
|
);
|
|
9896
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
|
+
}
|
|
9897
9962
|
/**
|
|
9898
9963
|
* 获取消息预览
|
|
9899
9964
|
*/
|
|
@@ -18181,22 +18246,23 @@ var SkillCommand = class extends SlashCommand {
|
|
|
18181
18246
|
*
|
|
18182
18247
|
* @param args 命令参数
|
|
18183
18248
|
*/
|
|
18184
|
-
async execute(args) {
|
|
18249
|
+
async execute(args, app) {
|
|
18185
18250
|
const subcommand = args[0];
|
|
18251
|
+
const sessionService = app.getContainer().get("session");
|
|
18186
18252
|
switch (subcommand) {
|
|
18187
18253
|
case "add":
|
|
18188
|
-
await this.handleAdd(args.slice(1));
|
|
18254
|
+
await this.handleAdd(args.slice(1), sessionService);
|
|
18189
18255
|
break;
|
|
18190
18256
|
case "remove":
|
|
18191
18257
|
case "rm":
|
|
18192
|
-
await this.handleRemove(args.slice(1));
|
|
18258
|
+
await this.handleRemove(args.slice(1), sessionService);
|
|
18193
18259
|
break;
|
|
18194
18260
|
case "list":
|
|
18195
18261
|
case "ls":
|
|
18196
|
-
await this.handleList();
|
|
18262
|
+
await this.handleList(sessionService);
|
|
18197
18263
|
break;
|
|
18198
18264
|
default:
|
|
18199
|
-
this.showHelp();
|
|
18265
|
+
await this.showHelp(sessionService);
|
|
18200
18266
|
}
|
|
18201
18267
|
}
|
|
18202
18268
|
/**
|
|
@@ -18204,10 +18270,12 @@ var SkillCommand = class extends SlashCommand {
|
|
|
18204
18270
|
*
|
|
18205
18271
|
* 从 GitHub 安装技能
|
|
18206
18272
|
*/
|
|
18207
|
-
async handleAdd(args) {
|
|
18273
|
+
async handleAdd(args, sessionService) {
|
|
18208
18274
|
if (args.length === 0) {
|
|
18209
|
-
|
|
18210
|
-
|
|
18275
|
+
await this.output(
|
|
18276
|
+
sessionService,
|
|
18277
|
+
"Error: GitHub source is required\nUsage: /skill add <user/repo> [--name <name>] [--overwrite]"
|
|
18278
|
+
);
|
|
18211
18279
|
return;
|
|
18212
18280
|
}
|
|
18213
18281
|
const source = args[0];
|
|
@@ -18223,8 +18291,12 @@ var SkillCommand = class extends SlashCommand {
|
|
|
18223
18291
|
}
|
|
18224
18292
|
try {
|
|
18225
18293
|
await this.skillManager.addSkill(source, options);
|
|
18294
|
+
await this.output(
|
|
18295
|
+
sessionService,
|
|
18296
|
+
`\u2705 Skill installed: ${options.name || source.split("/").pop() || source}`
|
|
18297
|
+
);
|
|
18226
18298
|
} catch (error) {
|
|
18227
|
-
|
|
18299
|
+
await this.output(sessionService, `Error: ${error}`);
|
|
18228
18300
|
}
|
|
18229
18301
|
}
|
|
18230
18302
|
/**
|
|
@@ -18232,17 +18304,20 @@ var SkillCommand = class extends SlashCommand {
|
|
|
18232
18304
|
*
|
|
18233
18305
|
* 删除已安装的技能
|
|
18234
18306
|
*/
|
|
18235
|
-
async handleRemove(args) {
|
|
18307
|
+
async handleRemove(args, sessionService) {
|
|
18236
18308
|
if (args.length === 0) {
|
|
18237
|
-
|
|
18238
|
-
|
|
18309
|
+
await this.output(
|
|
18310
|
+
sessionService,
|
|
18311
|
+
"Error: Skill name is required\nUsage: /skill remove <name>"
|
|
18312
|
+
);
|
|
18239
18313
|
return;
|
|
18240
18314
|
}
|
|
18241
18315
|
const name = args[0];
|
|
18242
18316
|
try {
|
|
18243
18317
|
await this.skillManager.removeSkill(name);
|
|
18318
|
+
await this.output(sessionService, `\u2705 Skill removed: ${name}`);
|
|
18244
18319
|
} catch (error) {
|
|
18245
|
-
|
|
18320
|
+
await this.output(sessionService, `Error: ${error}`);
|
|
18246
18321
|
}
|
|
18247
18322
|
}
|
|
18248
18323
|
/**
|
|
@@ -18250,25 +18325,28 @@ var SkillCommand = class extends SlashCommand {
|
|
|
18250
18325
|
*
|
|
18251
18326
|
* 列出所有可用的技能
|
|
18252
18327
|
*/
|
|
18253
|
-
async handleList() {
|
|
18328
|
+
async handleList(sessionService) {
|
|
18254
18329
|
const skills = this.skillManager.listSkills();
|
|
18255
18330
|
if (skills.length === 0) {
|
|
18256
|
-
|
|
18331
|
+
await this.output(sessionService, "No skills found");
|
|
18257
18332
|
return;
|
|
18258
18333
|
}
|
|
18259
|
-
|
|
18334
|
+
const lines = ["Available Skills:", ""];
|
|
18260
18335
|
for (const skill of skills) {
|
|
18261
|
-
|
|
18262
|
-
|
|
18263
|
-
|
|
18264
|
-
|
|
18336
|
+
lines.push(` /${skill.name}`);
|
|
18337
|
+
lines.push(` ${skill.description}`);
|
|
18338
|
+
lines.push(` Source: ${skill.source}`);
|
|
18339
|
+
lines.push("");
|
|
18265
18340
|
}
|
|
18341
|
+
await this.output(sessionService, lines.join("\n").trimEnd());
|
|
18266
18342
|
}
|
|
18267
18343
|
/**
|
|
18268
18344
|
* 显示帮助信息
|
|
18269
18345
|
*/
|
|
18270
|
-
showHelp() {
|
|
18271
|
-
|
|
18346
|
+
async showHelp(sessionService) {
|
|
18347
|
+
await this.output(
|
|
18348
|
+
sessionService,
|
|
18349
|
+
`
|
|
18272
18350
|
Usage: /skill <subcommand> [options]
|
|
18273
18351
|
|
|
18274
18352
|
Subcommands:
|
|
@@ -18282,7 +18360,18 @@ Examples:
|
|
|
18282
18360
|
/skill add user/repo --name my-skill --overwrite
|
|
18283
18361
|
/skill remove my-skill
|
|
18284
18362
|
/skill list
|
|
18285
|
-
|
|
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);
|
|
18286
18375
|
}
|
|
18287
18376
|
};
|
|
18288
18377
|
|
|
@@ -18298,86 +18387,95 @@ var AgentCommand = class extends SlashCommand {
|
|
|
18298
18387
|
super();
|
|
18299
18388
|
this.agentManager = agentManager;
|
|
18300
18389
|
}
|
|
18301
|
-
async execute(args) {
|
|
18390
|
+
async execute(args, app) {
|
|
18391
|
+
const sessionService = app.getContainer().get("session");
|
|
18302
18392
|
if (args.length === 0) {
|
|
18303
|
-
this.showHelp();
|
|
18393
|
+
await this.showHelp(sessionService);
|
|
18304
18394
|
return;
|
|
18305
18395
|
}
|
|
18306
18396
|
const subcommand = args[0];
|
|
18307
18397
|
if (subcommand === "list") {
|
|
18308
|
-
this.listAgents();
|
|
18398
|
+
await this.listAgents(sessionService);
|
|
18309
18399
|
return;
|
|
18310
18400
|
}
|
|
18311
18401
|
const agentName = subcommand;
|
|
18312
18402
|
const goal = args.slice(1).join(" ");
|
|
18313
18403
|
if (!goal) {
|
|
18314
|
-
|
|
18315
|
-
|
|
18404
|
+
await this.output(
|
|
18405
|
+
sessionService,
|
|
18406
|
+
`\u274C Please provide a goal for the agent
|
|
18407
|
+
Usage: /agent ${agentName} <goal>`
|
|
18408
|
+
);
|
|
18316
18409
|
return;
|
|
18317
18410
|
}
|
|
18318
|
-
await this.delegateTask(agentName, goal);
|
|
18411
|
+
await this.delegateTask(agentName, goal, sessionService);
|
|
18319
18412
|
}
|
|
18320
18413
|
/**
|
|
18321
18414
|
* 显示帮助信息
|
|
18322
18415
|
*/
|
|
18323
|
-
showHelp() {
|
|
18324
|
-
|
|
18325
|
-
|
|
18326
|
-
|
|
18327
|
-
|
|
18328
|
-
|
|
18329
|
-
|
|
18330
|
-
|
|
18331
|
-
|
|
18332
|
-
|
|
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
|
+
);
|
|
18333
18431
|
}
|
|
18334
18432
|
/**
|
|
18335
18433
|
* 列出所有 Agent
|
|
18336
18434
|
*/
|
|
18337
|
-
listAgents() {
|
|
18435
|
+
async listAgents(sessionService) {
|
|
18338
18436
|
const agents = this.agentManager.listAll();
|
|
18339
18437
|
if (agents.length === 0) {
|
|
18340
|
-
|
|
18438
|
+
await this.output(sessionService, "No agents available");
|
|
18341
18439
|
return;
|
|
18342
18440
|
}
|
|
18343
|
-
|
|
18344
|
-
\u{1F4CB} Available Agents (${agents.length}):
|
|
18345
|
-
`);
|
|
18441
|
+
const lines = [`\u{1F4CB} Available Agents (${agents.length}):`, ""];
|
|
18346
18442
|
for (const agent of agents) {
|
|
18347
|
-
|
|
18348
|
-
|
|
18443
|
+
lines.push(` \u{1F916} ${agent.name} (${agent.source})`);
|
|
18444
|
+
lines.push(` ${agent.description}`);
|
|
18349
18445
|
if (agent.tools) {
|
|
18350
|
-
|
|
18446
|
+
lines.push(` Tools: ${agent.tools.join(", ")}`);
|
|
18351
18447
|
}
|
|
18352
18448
|
if (agent.disallowedTools) {
|
|
18353
|
-
|
|
18449
|
+
lines.push(` Disallowed: ${agent.disallowedTools.join(", ")}`);
|
|
18354
18450
|
}
|
|
18355
18451
|
if (agent.model) {
|
|
18356
|
-
|
|
18452
|
+
lines.push(` Model: ${agent.model}`);
|
|
18357
18453
|
}
|
|
18358
18454
|
if (agent.forkContext) {
|
|
18359
|
-
|
|
18455
|
+
lines.push(` Fork Context: ${agent.forkContext}`);
|
|
18360
18456
|
}
|
|
18361
18457
|
if (agent.color) {
|
|
18362
|
-
|
|
18458
|
+
lines.push(` Color: ${agent.color}`);
|
|
18363
18459
|
}
|
|
18364
|
-
|
|
18460
|
+
lines.push("");
|
|
18365
18461
|
}
|
|
18462
|
+
await this.output(sessionService, lines.join("\n").trimEnd());
|
|
18366
18463
|
}
|
|
18367
18464
|
/**
|
|
18368
18465
|
* 委托任务给 Agent
|
|
18369
18466
|
*/
|
|
18370
|
-
async delegateTask(agentName, goal) {
|
|
18467
|
+
async delegateTask(agentName, goal, sessionService) {
|
|
18371
18468
|
if (!this.agentManager.has(agentName)) {
|
|
18372
|
-
|
|
18373
|
-
|
|
18469
|
+
await this.output(
|
|
18470
|
+
sessionService,
|
|
18471
|
+
`\u274C Agent not found: ${agentName}
|
|
18472
|
+
\u{1F4A1} Use /agent list to see available agents`
|
|
18473
|
+
);
|
|
18374
18474
|
return;
|
|
18375
18475
|
}
|
|
18376
18476
|
try {
|
|
18377
|
-
|
|
18378
|
-
|
|
18379
|
-
console.log(` Goal: ${goal}
|
|
18380
|
-
`);
|
|
18477
|
+
await this.output(sessionService, `\u{1F916} Delegating task to ${agentName}...
|
|
18478
|
+
Goal: ${goal}`);
|
|
18381
18479
|
const result = await this.agentManager.delegate(
|
|
18382
18480
|
{
|
|
18383
18481
|
type: "custom",
|
|
@@ -18386,26 +18484,41 @@ var AgentCommand = class extends SlashCommand {
|
|
|
18386
18484
|
agentName
|
|
18387
18485
|
);
|
|
18388
18486
|
if (result.success) {
|
|
18389
|
-
|
|
18390
|
-
\u2705 Task completed by ${agentName}`);
|
|
18487
|
+
let message = `\u2705 Task completed by ${agentName}`;
|
|
18391
18488
|
if (result.message) {
|
|
18392
|
-
|
|
18489
|
+
message += `
|
|
18490
|
+
${result.message}`;
|
|
18393
18491
|
}
|
|
18394
18492
|
if (result.data) {
|
|
18395
|
-
|
|
18493
|
+
message += `
|
|
18494
|
+
Data: ${JSON.stringify(result.data, null, 2)}`;
|
|
18396
18495
|
}
|
|
18496
|
+
await this.output(sessionService, message);
|
|
18397
18497
|
} else {
|
|
18398
|
-
|
|
18399
|
-
\u274C Task failed`);
|
|
18498
|
+
let message = "\u274C Task failed";
|
|
18400
18499
|
if (result.message) {
|
|
18401
|
-
|
|
18500
|
+
message += `
|
|
18501
|
+
${result.message}`;
|
|
18402
18502
|
}
|
|
18503
|
+
await this.output(sessionService, message);
|
|
18403
18504
|
}
|
|
18404
18505
|
} catch (error) {
|
|
18405
|
-
|
|
18406
|
-
|
|
18506
|
+
await this.output(
|
|
18507
|
+
sessionService,
|
|
18508
|
+
`\u274C Error: ${error instanceof Error ? error.message : String(error)}`
|
|
18509
|
+
);
|
|
18407
18510
|
}
|
|
18408
18511
|
}
|
|
18512
|
+
async output(sessionService, message) {
|
|
18513
|
+
if (sessionService) {
|
|
18514
|
+
await sessionService.addMessage({
|
|
18515
|
+
role: "assistant",
|
|
18516
|
+
content: message
|
|
18517
|
+
});
|
|
18518
|
+
return;
|
|
18519
|
+
}
|
|
18520
|
+
console.log(message);
|
|
18521
|
+
}
|
|
18409
18522
|
};
|
|
18410
18523
|
|
|
18411
18524
|
// src/commands/git/CommitCommand.ts
|
|
@@ -18422,53 +18535,83 @@ var CommitCommand = class extends SlashCommand {
|
|
|
18422
18535
|
this.modelService = modelService;
|
|
18423
18536
|
this.configManager = configManager;
|
|
18424
18537
|
}
|
|
18425
|
-
async execute(args) {
|
|
18538
|
+
async execute(args, app) {
|
|
18426
18539
|
const options = this.parseOptions(args);
|
|
18540
|
+
const sessionService = app.getContainer().get("session");
|
|
18427
18541
|
try {
|
|
18428
18542
|
if (options.stage) {
|
|
18429
|
-
|
|
18543
|
+
await this.output(sessionService, "\u{1F4E6} Staging all changes...");
|
|
18430
18544
|
this.execCommand("git add -A");
|
|
18431
18545
|
}
|
|
18432
|
-
|
|
18546
|
+
await this.output(sessionService, "\u{1F50D} Analyzing changes...");
|
|
18433
18547
|
const diff = await this.getDiff(true);
|
|
18434
18548
|
if (!diff || diff.trim().length === 0) {
|
|
18435
|
-
|
|
18549
|
+
await this.output(
|
|
18550
|
+
sessionService,
|
|
18551
|
+
"\u274C No staged changes to commit. Stage files first or run `/commit --stage`."
|
|
18552
|
+
);
|
|
18436
18553
|
return;
|
|
18437
18554
|
}
|
|
18438
18555
|
let commitHistory = "";
|
|
18439
18556
|
if (options.followStyle) {
|
|
18440
|
-
|
|
18557
|
+
await this.output(sessionService, "\u{1F4DA} Learning commit style from history...");
|
|
18441
18558
|
const history = await this.getCommitHistory(50);
|
|
18442
18559
|
commitHistory = history.join("\n");
|
|
18443
18560
|
}
|
|
18444
|
-
|
|
18561
|
+
await this.output(sessionService, "\u{1F916} Generating commit message...");
|
|
18445
18562
|
const commitMessage = await this.generateCommitMessage(diff, commitHistory, options);
|
|
18446
18563
|
if (options.copy) {
|
|
18447
18564
|
await this.copyToClipboard(commitMessage);
|
|
18448
|
-
|
|
18449
|
-
|
|
18565
|
+
await this.output(
|
|
18566
|
+
sessionService,
|
|
18567
|
+
`\u{1F4CB} Commit message copied to clipboard
|
|
18568
|
+
|
|
18569
|
+
${commitMessage}`
|
|
18570
|
+
);
|
|
18450
18571
|
return;
|
|
18451
18572
|
}
|
|
18452
|
-
console.log("\n\u{1F4DD} Generated commit message:\n");
|
|
18453
|
-
console.log(commitMessage);
|
|
18454
|
-
console.log("");
|
|
18455
18573
|
if (!options.commit) {
|
|
18456
|
-
|
|
18457
|
-
|
|
18458
|
-
|
|
18459
|
-
|
|
18460
|
-
|
|
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;
|
|
18461
18583
|
}
|
|
18584
|
+
await this.output(
|
|
18585
|
+
sessionService,
|
|
18586
|
+
`\u{1F4DD} Generated commit message:
|
|
18587
|
+
|
|
18588
|
+
${commitMessage}
|
|
18589
|
+
|
|
18590
|
+
\u{1F680} Creating commit...`
|
|
18591
|
+
);
|
|
18462
18592
|
await this.executeCommit(commitMessage, options);
|
|
18463
|
-
|
|
18593
|
+
await this.output(sessionService, "\u2705 Commit successful");
|
|
18464
18594
|
if (options.push) {
|
|
18465
|
-
|
|
18595
|
+
await this.output(sessionService, "\u{1F4E4} Pushing to remote...");
|
|
18466
18596
|
this.execCommand("git push");
|
|
18467
|
-
|
|
18597
|
+
await this.output(sessionService, "\u2705 Push successful");
|
|
18468
18598
|
}
|
|
18469
18599
|
} catch (error) {
|
|
18470
|
-
|
|
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;
|
|
18471
18613
|
}
|
|
18614
|
+
console.log(message);
|
|
18472
18615
|
}
|
|
18473
18616
|
/**
|
|
18474
18617
|
* 解析命令选项
|
|
@@ -18615,17 +18758,6 @@ Requirements:
|
|
|
18615
18758
|
|
|
18616
18759
|
Output only the commit message, no explanations.`;
|
|
18617
18760
|
}
|
|
18618
|
-
/**
|
|
18619
|
-
* 确认提交
|
|
18620
|
-
*/
|
|
18621
|
-
async confirmCommit() {
|
|
18622
|
-
console.log("Press Enter to commit, or Ctrl+C to cancel...");
|
|
18623
|
-
return new Promise((resolve11) => {
|
|
18624
|
-
process.stdin.once("data", () => {
|
|
18625
|
-
resolve11(true);
|
|
18626
|
-
});
|
|
18627
|
-
});
|
|
18628
|
-
}
|
|
18629
18761
|
/**
|
|
18630
18762
|
* 执行提交
|
|
18631
18763
|
*/
|
|
@@ -21106,6 +21238,18 @@ function useSession() {
|
|
|
21106
21238
|
const { app, currentSession, setCurrentSession, setSessions } = useAppContext();
|
|
21107
21239
|
const sessionService = app.getContainer().get("session");
|
|
21108
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
|
+
};
|
|
21109
21253
|
useEffect(() => {
|
|
21110
21254
|
const initSession = async () => {
|
|
21111
21255
|
try {
|
|
@@ -21145,11 +21289,31 @@ function useSession() {
|
|
|
21145
21289
|
const handleSessionLoaded = (data) => {
|
|
21146
21290
|
setCurrentSession(data.session);
|
|
21147
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
|
+
};
|
|
21148
21304
|
eventBus.on("session.created" /* SESSION_CREATED */, handleSessionCreated);
|
|
21149
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);
|
|
21150
21310
|
return () => {
|
|
21151
21311
|
eventBus.off("session.created" /* SESSION_CREATED */, handleSessionCreated);
|
|
21152
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);
|
|
21153
21317
|
};
|
|
21154
21318
|
}, [sessionService, eventBus, setCurrentSession, setSessions]);
|
|
21155
21319
|
return {
|
|
@@ -21391,6 +21555,7 @@ var EnhancedMessageList = ({
|
|
|
21391
21555
|
|
|
21392
21556
|
// src/ui/components/SimpleInput.tsx
|
|
21393
21557
|
init_esm_shims();
|
|
21558
|
+
var MAX_VISIBLE_SUGGESTIONS = 8;
|
|
21394
21559
|
var SimpleSuggestionEngine = class {
|
|
21395
21560
|
commands = [
|
|
21396
21561
|
"/help",
|
|
@@ -21463,6 +21628,7 @@ var SimpleInput = ({
|
|
|
21463
21628
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
21464
21629
|
const [showSuggestions, setShowSuggestions] = useState(false);
|
|
21465
21630
|
const suggestionEngine = useRef(new SimpleSuggestionEngine());
|
|
21631
|
+
const submittedValueRef = useRef(null);
|
|
21466
21632
|
useEffect(() => {
|
|
21467
21633
|
if (input.startsWith("/")) {
|
|
21468
21634
|
const newSuggestions = suggestionEngine.current.getSuggestions(input);
|
|
@@ -21481,7 +21647,13 @@ var SimpleInput = ({
|
|
|
21481
21647
|
} else if (key.downArrow) {
|
|
21482
21648
|
setSelectedIndex((prev) => prev === suggestions.length - 1 ? 0 : prev + 1);
|
|
21483
21649
|
} else if (key.return && suggestions[selectedIndex]) {
|
|
21484
|
-
|
|
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
|
+
}
|
|
21485
21657
|
setShowSuggestions(false);
|
|
21486
21658
|
} else if (key.escape) {
|
|
21487
21659
|
setShowSuggestions(false);
|
|
@@ -21493,6 +21665,7 @@ var SimpleInput = ({
|
|
|
21493
21665
|
const handleSubmit = useCallback(
|
|
21494
21666
|
(value) => {
|
|
21495
21667
|
if (!value.trim() || disabled) return;
|
|
21668
|
+
submittedValueRef.current = value;
|
|
21496
21669
|
setInput("");
|
|
21497
21670
|
setShowSuggestions(false);
|
|
21498
21671
|
onSubmit(value);
|
|
@@ -21501,6 +21674,16 @@ var SimpleInput = ({
|
|
|
21501
21674
|
);
|
|
21502
21675
|
const promptSymbol = ">";
|
|
21503
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
|
+
) : [];
|
|
21504
21687
|
const getStatusIndicator = () => {
|
|
21505
21688
|
switch (status) {
|
|
21506
21689
|
case "thinking":
|
|
@@ -21513,7 +21696,7 @@ var SimpleInput = ({
|
|
|
21513
21696
|
return "";
|
|
21514
21697
|
}
|
|
21515
21698
|
};
|
|
21516
|
-
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(
|
|
21517
21700
|
TextInput,
|
|
21518
21701
|
{
|
|
21519
21702
|
value: input,
|
|
@@ -21521,21 +21704,22 @@ var SimpleInput = ({
|
|
|
21521
21704
|
onSubmit: handleSubmit,
|
|
21522
21705
|
placeholder
|
|
21523
21706
|
}
|
|
21524
|
-
))), /* @__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(
|
|
21525
21708
|
Text,
|
|
21526
21709
|
{
|
|
21527
21710
|
color: index === selectedIndex ? "cyan" : "gray",
|
|
21528
21711
|
bold: index === selectedIndex
|
|
21529
21712
|
},
|
|
21530
21713
|
suggestion.text
|
|
21531
|
-
)), /* @__PURE__ */ React.createElement(
|
|
21714
|
+
)), /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }, /* @__PURE__ */ React.createElement(
|
|
21532
21715
|
Text,
|
|
21533
21716
|
{
|
|
21534
21717
|
color: index === selectedIndex ? "white" : "dim",
|
|
21535
|
-
dimColor: index !== selectedIndex
|
|
21718
|
+
dimColor: index !== selectedIndex,
|
|
21719
|
+
wrap: "truncate-end"
|
|
21536
21720
|
},
|
|
21537
21721
|
suggestion.description
|
|
21538
|
-
))), /* @__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"))));
|
|
21539
21723
|
};
|
|
21540
21724
|
|
|
21541
21725
|
// src/ui/components/WelcomeScreen.tsx
|
|
@@ -22061,6 +22245,20 @@ function AppContent() {
|
|
|
22061
22245
|
const [showResumeSelector, setShowResumeSelector] = useState(false);
|
|
22062
22246
|
const [showMcpManager, setShowMcpManager] = useState(false);
|
|
22063
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]);
|
|
22064
22262
|
const messagesRef = useRef([]);
|
|
22065
22263
|
const [, forceUpdate] = useState({});
|
|
22066
22264
|
const historyMessages = messagesRef.current;
|
|
@@ -22184,6 +22382,16 @@ function AppContent() {
|
|
|
22184
22382
|
useInput(
|
|
22185
22383
|
useCallback(
|
|
22186
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
|
+
}
|
|
22187
22395
|
if (key.ctrl && input === "o") {
|
|
22188
22396
|
clearTerminal();
|
|
22189
22397
|
toggleTranscriptMode();
|
|
@@ -22191,7 +22399,7 @@ function AppContent() {
|
|
|
22191
22399
|
return;
|
|
22192
22400
|
}
|
|
22193
22401
|
if (transcriptMode) {
|
|
22194
|
-
if (key.escape
|
|
22402
|
+
if (key.escape) {
|
|
22195
22403
|
clearTerminal();
|
|
22196
22404
|
toggleTranscriptMode();
|
|
22197
22405
|
refresh();
|
|
@@ -22202,7 +22410,17 @@ function AppContent() {
|
|
|
22202
22410
|
return;
|
|
22203
22411
|
}
|
|
22204
22412
|
},
|
|
22205
|
-
[
|
|
22413
|
+
[
|
|
22414
|
+
transcriptMode,
|
|
22415
|
+
toggleTranscriptMode,
|
|
22416
|
+
refresh,
|
|
22417
|
+
showModelSelector,
|
|
22418
|
+
showRewindSelector,
|
|
22419
|
+
showResumeSelector,
|
|
22420
|
+
showMcpManager,
|
|
22421
|
+
showStatusManager,
|
|
22422
|
+
resetTransientUi
|
|
22423
|
+
]
|
|
22206
22424
|
)
|
|
22207
22425
|
);
|
|
22208
22426
|
const handleSubmit = useCallback(
|
|
@@ -22216,7 +22434,7 @@ function AppContent() {
|
|
|
22216
22434
|
return;
|
|
22217
22435
|
}
|
|
22218
22436
|
if (value.trim().toLowerCase() === "exit" || value.trim().toLowerCase() === "quit") {
|
|
22219
|
-
|
|
22437
|
+
await requestAppExit();
|
|
22220
22438
|
return;
|
|
22221
22439
|
}
|
|
22222
22440
|
setTasks([]);
|
|
@@ -22256,7 +22474,7 @@ function AppContent() {
|
|
|
22256
22474
|
setIsLoading(false);
|
|
22257
22475
|
}
|
|
22258
22476
|
},
|
|
22259
|
-
[currentSession, app, sessionService,
|
|
22477
|
+
[currentSession, app, sessionService, requestAppExit]
|
|
22260
22478
|
);
|
|
22261
22479
|
const handleModelSelect = useCallback(
|
|
22262
22480
|
async (modelId) => {
|
|
@@ -22379,6 +22597,16 @@ function AppContent() {
|
|
|
22379
22597
|
eventBus.off("show_model_selector", handleShowModelSelector);
|
|
22380
22598
|
};
|
|
22381
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]);
|
|
22382
22610
|
useEffect(() => {
|
|
22383
22611
|
const eventBus = app.getContainer().get("eventBus");
|
|
22384
22612
|
const handleShowRewindSelector = () => {
|
|
@@ -22746,7 +22974,9 @@ program.command("chat", { isDefault: true }).description("Start interactive chat
|
|
|
22746
22974
|
await sessionService.initialize();
|
|
22747
22975
|
console.log("\u2705 SessionService initialized");
|
|
22748
22976
|
console.log("\n\u{1F3A8} Starting interactive UI...\n");
|
|
22749
|
-
render(React.createElement(App, { app }));
|
|
22977
|
+
const inkApp = render(React.createElement(App, { app }));
|
|
22978
|
+
await inkApp.waitUntilExit();
|
|
22979
|
+
process.exit(0);
|
|
22750
22980
|
} catch (error) {
|
|
22751
22981
|
console.error("\u274C Fatal error:", error);
|
|
22752
22982
|
process.exit(1);
|