@involvex/super-agent-cli 0.0.60 → 0.0.62
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/index.js +1193 -696
- package/dist/super-agent-cli.exe +0 -0
- package/eslint.config.mjs +11 -0
- package/package.json +9 -1
- package/tsc_output.txt +2 -0
package/dist/index.js
CHANGED
|
@@ -536,11 +536,122 @@ var init_indexer = __esm(() => {
|
|
|
536
536
|
init_settings_manager();
|
|
537
537
|
});
|
|
538
538
|
|
|
539
|
+
// src/utils/session-manager.ts
|
|
540
|
+
var exports_session_manager = {};
|
|
541
|
+
__export(exports_session_manager, {
|
|
542
|
+
getSessionManager: () => getSessionManager,
|
|
543
|
+
SessionManager: () => SessionManager
|
|
544
|
+
});
|
|
545
|
+
import * as fs13 from "fs-extra";
|
|
546
|
+
import * as path12 from "path";
|
|
547
|
+
|
|
548
|
+
class SessionManager {
|
|
549
|
+
static instance;
|
|
550
|
+
sessionsDir;
|
|
551
|
+
currentSession = null;
|
|
552
|
+
constructor() {
|
|
553
|
+
const settingsManager = getSettingsManager();
|
|
554
|
+
this.sessionsDir = path12.join(settingsManager.getStorageDirectory(), "sessions");
|
|
555
|
+
fs13.ensureDirSync(this.sessionsDir);
|
|
556
|
+
}
|
|
557
|
+
static getInstance() {
|
|
558
|
+
if (!SessionManager.instance) {
|
|
559
|
+
SessionManager.instance = new SessionManager;
|
|
560
|
+
}
|
|
561
|
+
return SessionManager.instance;
|
|
562
|
+
}
|
|
563
|
+
generateSessionId(workingDir) {
|
|
564
|
+
const normalized = path12.normalize(workingDir).toLowerCase();
|
|
565
|
+
return Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
566
|
+
}
|
|
567
|
+
getSessionFilePath(sessionId) {
|
|
568
|
+
return path12.join(this.sessionsDir, `${sessionId}.json`);
|
|
569
|
+
}
|
|
570
|
+
async getOrCreateSession(workingDirectory, name) {
|
|
571
|
+
const sessionId = this.generateSessionId(workingDirectory);
|
|
572
|
+
const sessionFile = this.getSessionFilePath(sessionId);
|
|
573
|
+
try {
|
|
574
|
+
if (await fs13.pathExists(sessionFile)) {
|
|
575
|
+
const session = await fs13.readJson(sessionFile);
|
|
576
|
+
session.lastAccessed = Date.now();
|
|
577
|
+
this.currentSession = session;
|
|
578
|
+
await this.saveSession(session);
|
|
579
|
+
return session;
|
|
580
|
+
}
|
|
581
|
+
} catch (error) {}
|
|
582
|
+
const newSession = {
|
|
583
|
+
id: sessionId,
|
|
584
|
+
workingDirectory,
|
|
585
|
+
name: name || path12.basename(workingDirectory),
|
|
586
|
+
messages: [],
|
|
587
|
+
lastAccessed: Date.now(),
|
|
588
|
+
createdAt: Date.now()
|
|
589
|
+
};
|
|
590
|
+
this.currentSession = newSession;
|
|
591
|
+
await this.saveSession(newSession);
|
|
592
|
+
return newSession;
|
|
593
|
+
}
|
|
594
|
+
async saveSession(session) {
|
|
595
|
+
const sessionFile = this.getSessionFilePath(session.id);
|
|
596
|
+
await fs13.outputJson(sessionFile, session, { spaces: 2 });
|
|
597
|
+
}
|
|
598
|
+
async addMessage(message) {
|
|
599
|
+
if (!this.currentSession) {
|
|
600
|
+
throw new Error("No active session");
|
|
601
|
+
}
|
|
602
|
+
this.currentSession.messages.push(message);
|
|
603
|
+
this.currentSession.lastAccessed = Date.now();
|
|
604
|
+
await this.saveSession(this.currentSession);
|
|
605
|
+
}
|
|
606
|
+
async listSessions() {
|
|
607
|
+
const sessionFiles = await fs13.readdir(this.sessionsDir);
|
|
608
|
+
const sessions = [];
|
|
609
|
+
for (const file of sessionFiles) {
|
|
610
|
+
if (file.endsWith(".json")) {
|
|
611
|
+
try {
|
|
612
|
+
const session = await fs13.readJson(path12.join(this.sessionsDir, file));
|
|
613
|
+
sessions.push(session);
|
|
614
|
+
} catch (error) {}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
sessions.sort((a, b) => b.lastAccessed - a.lastAccessed);
|
|
618
|
+
return sessions;
|
|
619
|
+
}
|
|
620
|
+
async deleteSession(sessionId) {
|
|
621
|
+
const sessionFile = this.getSessionFilePath(sessionId);
|
|
622
|
+
if (await fs13.pathExists(sessionFile)) {
|
|
623
|
+
await fs13.remove(sessionFile);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
getCurrentSession() {
|
|
627
|
+
return this.currentSession;
|
|
628
|
+
}
|
|
629
|
+
async switchSession(sessionId) {
|
|
630
|
+
const sessionFile = this.getSessionFilePath(sessionId);
|
|
631
|
+
try {
|
|
632
|
+
if (await fs13.pathExists(sessionFile)) {
|
|
633
|
+
const session = await fs13.readJson(sessionFile);
|
|
634
|
+
session.lastAccessed = Date.now();
|
|
635
|
+
this.currentSession = session;
|
|
636
|
+
await this.saveSession(session);
|
|
637
|
+
return session;
|
|
638
|
+
}
|
|
639
|
+
} catch (error) {}
|
|
640
|
+
return null;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
function getSessionManager() {
|
|
644
|
+
return SessionManager.getInstance();
|
|
645
|
+
}
|
|
646
|
+
var init_session_manager = __esm(() => {
|
|
647
|
+
init_settings_manager();
|
|
648
|
+
});
|
|
649
|
+
|
|
539
650
|
// package.json
|
|
540
651
|
var require_package = __commonJS((exports, module) => {
|
|
541
652
|
module.exports = {
|
|
542
653
|
name: "@involvex/super-agent-cli",
|
|
543
|
-
version: "0.0.
|
|
654
|
+
version: "0.0.62",
|
|
544
655
|
description: "An open-source AI agent that brings the power of Super Agent directly into your terminal.",
|
|
545
656
|
keywords: [
|
|
546
657
|
"cli",
|
|
@@ -567,10 +678,15 @@ var require_package = __commonJS((exports, module) => {
|
|
|
567
678
|
bin: {
|
|
568
679
|
"super-agent": "dist/index.js"
|
|
569
680
|
},
|
|
681
|
+
workspaces: [
|
|
682
|
+
"@plugins/templates/*",
|
|
683
|
+
"@plugins/examples/*"
|
|
684
|
+
],
|
|
570
685
|
scripts: {
|
|
571
686
|
prebuild: "bun run format && bun run lint:fix && bun run typecheck",
|
|
572
687
|
build: "bun build src/index.ts --outdir ./dist --target node --packages external --format esm",
|
|
573
688
|
"build:bun": "bun build src/index.ts --outdir ./dist --target node --packages external --format esm",
|
|
689
|
+
"build:plugins": "bun run -F @involvex/super-agent\\* build",
|
|
574
690
|
changelog: "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
|
|
575
691
|
compile: "bun run prebuild && bun build --compile src/index.ts --outfile ./dist/super-agent-cli.exe --config bunfig.toml",
|
|
576
692
|
dev: "bun run --watch src/index.ts",
|
|
@@ -587,6 +703,7 @@ var require_package = __commonJS((exports, module) => {
|
|
|
587
703
|
dependencies: {
|
|
588
704
|
"@google/generative-ai": "^0.24.1",
|
|
589
705
|
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
706
|
+
"@types/mime": "^4.0.0",
|
|
590
707
|
axios: "^1.13.4",
|
|
591
708
|
cfonts: "^3.3.1",
|
|
592
709
|
chalk: "^5.6.2",
|
|
@@ -595,7 +712,9 @@ var require_package = __commonJS((exports, module) => {
|
|
|
595
712
|
dotenv: "^17.2.3",
|
|
596
713
|
enquirer: "^2.4.1",
|
|
597
714
|
"fs-extra": "^11.3.3",
|
|
715
|
+
ignore: "^7.0.5",
|
|
598
716
|
ink: "^6.6.0",
|
|
717
|
+
inquirer: "^13.2.2",
|
|
599
718
|
marked: "^17.0.1",
|
|
600
719
|
"marked-terminal": "^7.3.0",
|
|
601
720
|
mime: "^4.1.0",
|
|
@@ -633,46 +752,14 @@ var require_package = __commonJS((exports, module) => {
|
|
|
633
752
|
};
|
|
634
753
|
});
|
|
635
754
|
|
|
636
|
-
// src/utils/banner.ts
|
|
637
|
-
var exports_banner = {};
|
|
638
|
-
__export(exports_banner, {
|
|
639
|
-
HELP_BANNER: () => HELP_BANNER,
|
|
640
|
-
BANNER: () => BANNER
|
|
641
|
-
});
|
|
642
|
-
var BANNER = `
|
|
643
|
-
╔═══════════════════════════════════════════════════════════════╗
|
|
644
|
-
║ ║
|
|
645
|
-
║ ███████╗██╗ ██╗██████╗ ███████╗██████╗ ║
|
|
646
|
-
║ ██╔════╝██║ ██║██╔══██╗██╔════╝██╔══██╗ ║
|
|
647
|
-
║ ███████╗██║ ██║██████╔╝█████╗ ██████╔╝ ║
|
|
648
|
-
║ ╚════██║██║ ██║██╔═══╝ ██╔══╝ ██╔══██╗ ║
|
|
649
|
-
║ ███████║╚██████╔╝██║ ███████╗██║ ██║ ║
|
|
650
|
-
║ ╚══════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ║
|
|
651
|
-
║ ║
|
|
652
|
-
║ █████╗ ██████╗ ███████╗███╗ ██╗████████╗ ║
|
|
653
|
-
║ ██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝ ║
|
|
654
|
-
║ ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ║
|
|
655
|
-
║ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ║
|
|
656
|
-
║ ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ║
|
|
657
|
-
║ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ║
|
|
658
|
-
║ ║
|
|
659
|
-
║ \uD83E\uDD16 AI-Powered Terminal Assistant ║
|
|
660
|
-
║ ║
|
|
661
|
-
╚═══════════════════════════════════════════════════════════════╝
|
|
662
|
-
`, HELP_BANNER = `
|
|
663
|
-
╔═══════════════════════════════════════════╗
|
|
664
|
-
║ \uD83E\uDD16 SUPER AGENT - Help & Usage ║
|
|
665
|
-
╚═══════════════════════════════════════════╝
|
|
666
|
-
`;
|
|
667
|
-
|
|
668
755
|
// src/utils/update-checker.ts
|
|
669
756
|
var exports_update_checker = {};
|
|
670
757
|
__export(exports_update_checker, {
|
|
671
758
|
getUpdateChecker: () => getUpdateChecker,
|
|
672
759
|
UpdateChecker: () => UpdateChecker
|
|
673
760
|
});
|
|
674
|
-
import * as
|
|
675
|
-
import * as
|
|
761
|
+
import * as fs14 from "fs-extra";
|
|
762
|
+
import * as path13 from "path";
|
|
676
763
|
import axios3 from "axios";
|
|
677
764
|
|
|
678
765
|
class UpdateChecker {
|
|
@@ -681,7 +768,7 @@ class UpdateChecker {
|
|
|
681
768
|
currentVersion;
|
|
682
769
|
constructor(currentVersion) {
|
|
683
770
|
const settingsManager = getSettingsManager();
|
|
684
|
-
this.cacheFile =
|
|
771
|
+
this.cacheFile = path13.join(settingsManager.getStorageDirectory(), "update-cache.json");
|
|
685
772
|
this.currentVersion = currentVersion;
|
|
686
773
|
}
|
|
687
774
|
static getInstance(currentVersion) {
|
|
@@ -692,8 +779,8 @@ class UpdateChecker {
|
|
|
692
779
|
}
|
|
693
780
|
async loadCache() {
|
|
694
781
|
try {
|
|
695
|
-
if (await
|
|
696
|
-
const cache = await
|
|
782
|
+
if (await fs14.pathExists(this.cacheFile)) {
|
|
783
|
+
const cache = await fs14.readJson(this.cacheFile);
|
|
697
784
|
const now = Date.now();
|
|
698
785
|
if (cache.lastChecked && now - cache.lastChecked < CACHE_DURATION) {
|
|
699
786
|
return cache;
|
|
@@ -704,7 +791,7 @@ class UpdateChecker {
|
|
|
704
791
|
}
|
|
705
792
|
async saveCache(info) {
|
|
706
793
|
try {
|
|
707
|
-
await
|
|
794
|
+
await fs14.outputJson(this.cacheFile, info);
|
|
708
795
|
} catch (error) {}
|
|
709
796
|
}
|
|
710
797
|
compareVersions(v1, v2) {
|
|
@@ -773,459 +860,129 @@ var init_update_checker = __esm(() => {
|
|
|
773
860
|
CACHE_DURATION = 24 * 60 * 60 * 1000;
|
|
774
861
|
});
|
|
775
862
|
|
|
776
|
-
// src/utils/
|
|
777
|
-
var
|
|
778
|
-
__export(
|
|
779
|
-
|
|
780
|
-
|
|
863
|
+
// src/utils/banner.ts
|
|
864
|
+
var exports_banner = {};
|
|
865
|
+
__export(exports_banner, {
|
|
866
|
+
HELP_BANNER: () => HELP_BANNER,
|
|
867
|
+
BANNER: () => BANNER
|
|
781
868
|
});
|
|
782
|
-
|
|
783
|
-
|
|
869
|
+
var BANNER = `
|
|
870
|
+
╔═══════════════════════════════════════════════════════════════╗
|
|
871
|
+
║ ║
|
|
872
|
+
║ ███████╗██╗ ██╗██████╗ ███████╗██████╗ ║
|
|
873
|
+
║ ██╔════╝██║ ██║██╔══██╗██╔════╝██╔══██╗ ║
|
|
874
|
+
║ ███████╗██║ ██║██████╔╝█████╗ ██████╔╝ ║
|
|
875
|
+
║ ╚════██║██║ ██║██╔═══╝ ██╔══╝ ██╔══██╗ ║
|
|
876
|
+
║ ███████║╚██████╔╝██║ ███████╗██║ ██║ ║
|
|
877
|
+
║ ╚══════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ║
|
|
878
|
+
║ ║
|
|
879
|
+
║ █████╗ ██████╗ ███████╗███╗ ██╗████████╗ ║
|
|
880
|
+
║ ██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝ ║
|
|
881
|
+
║ ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ║
|
|
882
|
+
║ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ║
|
|
883
|
+
║ ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ║
|
|
884
|
+
║ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ║
|
|
885
|
+
║ ║
|
|
886
|
+
║ \uD83E\uDD16 AI-Powered Terminal Assistant ║
|
|
887
|
+
║ ║
|
|
888
|
+
╚═══════════════════════════════════════════════════════════════╝
|
|
889
|
+
`, HELP_BANNER = `
|
|
890
|
+
╔═══════════════════════════════════════════╗
|
|
891
|
+
║ \uD83E\uDD16 SUPER AGENT - Help & Usage ║
|
|
892
|
+
╚═══════════════════════════════════════════╝
|
|
893
|
+
`;
|
|
784
894
|
|
|
785
|
-
|
|
895
|
+
// src/utils/confirmation-service.ts
|
|
896
|
+
import { EventEmitter } from "events";
|
|
897
|
+
import { exec } from "child_process";
|
|
898
|
+
import { promisify } from "util";
|
|
899
|
+
var execAsync = promisify(exec);
|
|
900
|
+
|
|
901
|
+
class ConfirmationService extends EventEmitter {
|
|
786
902
|
static instance;
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
903
|
+
skipConfirmationThisSession = false;
|
|
904
|
+
pendingConfirmation = null;
|
|
905
|
+
resolveConfirmation = null;
|
|
906
|
+
sessionFlags = {
|
|
907
|
+
fileOperations: false,
|
|
908
|
+
bashCommands: false,
|
|
909
|
+
allOperations: false
|
|
910
|
+
};
|
|
794
911
|
static getInstance() {
|
|
795
|
-
if (!
|
|
796
|
-
|
|
912
|
+
if (!ConfirmationService.instance) {
|
|
913
|
+
ConfirmationService.instance = new ConfirmationService;
|
|
797
914
|
}
|
|
798
|
-
return
|
|
799
|
-
}
|
|
800
|
-
generateSessionId(workingDir) {
|
|
801
|
-
const normalized = path13.normalize(workingDir).toLowerCase();
|
|
802
|
-
return Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
803
|
-
}
|
|
804
|
-
getSessionFilePath(sessionId) {
|
|
805
|
-
return path13.join(this.sessionsDir, `${sessionId}.json`);
|
|
806
|
-
}
|
|
807
|
-
async getOrCreateSession(workingDirectory, name) {
|
|
808
|
-
const sessionId = this.generateSessionId(workingDirectory);
|
|
809
|
-
const sessionFile = this.getSessionFilePath(sessionId);
|
|
810
|
-
try {
|
|
811
|
-
if (await fs14.pathExists(sessionFile)) {
|
|
812
|
-
const session = await fs14.readJson(sessionFile);
|
|
813
|
-
session.lastAccessed = Date.now();
|
|
814
|
-
this.currentSession = session;
|
|
815
|
-
await this.saveSession(session);
|
|
816
|
-
return session;
|
|
817
|
-
}
|
|
818
|
-
} catch (error) {}
|
|
819
|
-
const newSession = {
|
|
820
|
-
id: sessionId,
|
|
821
|
-
workingDirectory,
|
|
822
|
-
name: name || path13.basename(workingDirectory),
|
|
823
|
-
messages: [],
|
|
824
|
-
lastAccessed: Date.now(),
|
|
825
|
-
createdAt: Date.now()
|
|
826
|
-
};
|
|
827
|
-
this.currentSession = newSession;
|
|
828
|
-
await this.saveSession(newSession);
|
|
829
|
-
return newSession;
|
|
915
|
+
return ConfirmationService.instance;
|
|
830
916
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
await fs14.outputJson(sessionFile, session, { spaces: 2 });
|
|
917
|
+
constructor() {
|
|
918
|
+
super();
|
|
834
919
|
}
|
|
835
|
-
async
|
|
836
|
-
if (
|
|
837
|
-
|
|
920
|
+
async requestConfirmation(options, operationType = "file") {
|
|
921
|
+
if (this.sessionFlags.allOperations || operationType === "file" && this.sessionFlags.fileOperations || operationType === "bash" && this.sessionFlags.bashCommands) {
|
|
922
|
+
return { confirmed: true };
|
|
838
923
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
const sessionFiles = await fs14.readdir(this.sessionsDir);
|
|
845
|
-
const sessions = [];
|
|
846
|
-
for (const file of sessionFiles) {
|
|
847
|
-
if (file.endsWith(".json")) {
|
|
848
|
-
try {
|
|
849
|
-
const session = await fs14.readJson(path13.join(this.sessionsDir, file));
|
|
850
|
-
sessions.push(session);
|
|
851
|
-
} catch (error) {}
|
|
924
|
+
if (options.showVSCodeOpen) {
|
|
925
|
+
try {
|
|
926
|
+
await this.openInVSCode(options.filename);
|
|
927
|
+
} catch (error) {
|
|
928
|
+
options.showVSCodeOpen = false;
|
|
852
929
|
}
|
|
853
930
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
}
|
|
857
|
-
async deleteSession(sessionId) {
|
|
858
|
-
const sessionFile = this.getSessionFilePath(sessionId);
|
|
859
|
-
if (await fs14.pathExists(sessionFile)) {
|
|
860
|
-
await fs14.remove(sessionFile);
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
getCurrentSession() {
|
|
864
|
-
return this.currentSession;
|
|
865
|
-
}
|
|
866
|
-
async switchSession(sessionId) {
|
|
867
|
-
const sessionFile = this.getSessionFilePath(sessionId);
|
|
868
|
-
try {
|
|
869
|
-
if (await fs14.pathExists(sessionFile)) {
|
|
870
|
-
const session = await fs14.readJson(sessionFile);
|
|
871
|
-
session.lastAccessed = Date.now();
|
|
872
|
-
this.currentSession = session;
|
|
873
|
-
await this.saveSession(session);
|
|
874
|
-
return session;
|
|
875
|
-
}
|
|
876
|
-
} catch (error) {}
|
|
877
|
-
return null;
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
function getSessionManager() {
|
|
881
|
-
return SessionManager.getInstance();
|
|
882
|
-
}
|
|
883
|
-
var init_session_manager = __esm(() => {
|
|
884
|
-
init_settings_manager();
|
|
885
|
-
});
|
|
886
|
-
|
|
887
|
-
// src/web/server.ts
|
|
888
|
-
var exports_server = {};
|
|
889
|
-
__export(exports_server, {
|
|
890
|
-
WebServer: () => WebServer
|
|
891
|
-
});
|
|
892
|
-
import { createServer } from "http";
|
|
893
|
-
import { WebSocketServer } from "ws";
|
|
894
|
-
import * as fs15 from "fs-extra";
|
|
895
|
-
import * as path14 from "path";
|
|
896
|
-
import open from "open";
|
|
897
|
-
import mime from "mime";
|
|
898
|
-
|
|
899
|
-
class WebServer {
|
|
900
|
-
httpServer;
|
|
901
|
-
wss;
|
|
902
|
-
agent;
|
|
903
|
-
hostname;
|
|
904
|
-
port;
|
|
905
|
-
clients = new Set;
|
|
906
|
-
constructor(options) {
|
|
907
|
-
this.hostname = options.hostname || "localhost";
|
|
908
|
-
this.port = options.port || 3000;
|
|
909
|
-
this.agent = options.agent;
|
|
910
|
-
this.httpServer = createServer((req, res) => {
|
|
911
|
-
this.handleHttpRequest(req, res);
|
|
931
|
+
this.pendingConfirmation = new Promise((resolve) => {
|
|
932
|
+
this.resolveConfirmation = resolve;
|
|
912
933
|
});
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
this.handleWebSocketConnection(ws);
|
|
934
|
+
setImmediate(() => {
|
|
935
|
+
this.emit("confirmation-requested", options);
|
|
916
936
|
});
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
const absolutePath = path14.resolve(clientDir, sanitizedPath.substring(1));
|
|
924
|
-
if (!absolutePath.startsWith(clientDir)) {
|
|
925
|
-
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
926
|
-
res.end("Forbidden");
|
|
927
|
-
return;
|
|
928
|
-
}
|
|
929
|
-
try {
|
|
930
|
-
if (await fs15.pathExists(absolutePath)) {
|
|
931
|
-
const stat5 = await fs15.stat(absolutePath);
|
|
932
|
-
let filePath = absolutePath;
|
|
933
|
-
if (stat5.isDirectory()) {
|
|
934
|
-
filePath = path14.join(absolutePath, "index.html");
|
|
935
|
-
}
|
|
936
|
-
const content = await fs15.readFile(filePath);
|
|
937
|
-
const mimeType = mime.getType(filePath) || "application/octet-stream";
|
|
938
|
-
res.writeHead(200, { "Content-Type": mimeType });
|
|
939
|
-
res.end(content);
|
|
940
|
-
} else {
|
|
941
|
-
res.writeHead(404);
|
|
942
|
-
res.end("Not Found");
|
|
937
|
+
const result = await this.pendingConfirmation;
|
|
938
|
+
if (result.dontAskAgain) {
|
|
939
|
+
if (operationType === "file") {
|
|
940
|
+
this.sessionFlags.fileOperations = true;
|
|
941
|
+
} else if (operationType === "bash") {
|
|
942
|
+
this.sessionFlags.bashCommands = true;
|
|
943
943
|
}
|
|
944
|
-
} catch (error) {
|
|
945
|
-
console.error("Error serving file:", error);
|
|
946
|
-
res.writeHead(500);
|
|
947
|
-
res.end("Internal Server Error");
|
|
948
944
|
}
|
|
945
|
+
return result;
|
|
949
946
|
}
|
|
950
|
-
|
|
951
|
-
this.
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
const message = JSON.parse(data.toString());
|
|
957
|
-
if (message.type === "prompt") {
|
|
958
|
-
await this.handlePrompt(message.content, ws);
|
|
959
|
-
} else if (message.type === "get_file_tree") {
|
|
960
|
-
await this.handleGetFileTree(ws);
|
|
961
|
-
} else if (message.type === "get_file_content") {
|
|
962
|
-
await this.handleGetFileContent(message.path, ws);
|
|
963
|
-
} else if (message.type === "list_sessions") {
|
|
964
|
-
await this.handleListSessions(ws);
|
|
965
|
-
} else if (message.type === "switch_session") {
|
|
966
|
-
await this.handleSwitchSession(message.sessionId, ws);
|
|
967
|
-
}
|
|
968
|
-
} catch (error) {
|
|
969
|
-
console.error("WebSocket message error:", error);
|
|
970
|
-
ws.send(JSON.stringify({ type: "error", content: "Invalid message format" }));
|
|
971
|
-
}
|
|
972
|
-
});
|
|
973
|
-
ws.on("close", () => {
|
|
974
|
-
this.clients.delete(ws);
|
|
975
|
-
console.log(`\uD83D\uDCE1 Web client disconnected (${this.clients.size} remaining)`);
|
|
976
|
-
});
|
|
977
|
-
ws.on("error", (error) => {
|
|
978
|
-
console.error("WebSocket error:", error);
|
|
979
|
-
});
|
|
947
|
+
confirmOperation(confirmed, dontAskAgain) {
|
|
948
|
+
if (this.resolveConfirmation) {
|
|
949
|
+
this.resolveConfirmation({ confirmed, dontAskAgain });
|
|
950
|
+
this.resolveConfirmation = null;
|
|
951
|
+
this.pendingConfirmation = null;
|
|
952
|
+
}
|
|
980
953
|
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
if (entry.type === "assistant") {
|
|
987
|
-
ws.send(JSON.stringify({
|
|
988
|
-
type: "assistant_message",
|
|
989
|
-
content: entry.content
|
|
990
|
-
}));
|
|
991
|
-
} else if (entry.type === "tool_call") {
|
|
992
|
-
ws.send(JSON.stringify({
|
|
993
|
-
type: "tool_call",
|
|
994
|
-
tool: entry.toolCall?.function.name,
|
|
995
|
-
content: "Executing..."
|
|
996
|
-
}));
|
|
997
|
-
} else if (entry.type === "tool_result") {
|
|
998
|
-
ws.send(JSON.stringify({
|
|
999
|
-
type: "tool_result",
|
|
1000
|
-
tool: entry.toolCall?.function.name,
|
|
1001
|
-
content: entry.content
|
|
1002
|
-
}));
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
ws.send(JSON.stringify({ type: "done" }));
|
|
1006
|
-
} catch (error) {
|
|
1007
|
-
ws.send(JSON.stringify({
|
|
1008
|
-
type: "error",
|
|
1009
|
-
content: error.message
|
|
1010
|
-
}));
|
|
954
|
+
rejectOperation(feedback) {
|
|
955
|
+
if (this.resolveConfirmation) {
|
|
956
|
+
this.resolveConfirmation({ confirmed: false, feedback });
|
|
957
|
+
this.resolveConfirmation = null;
|
|
958
|
+
this.pendingConfirmation = null;
|
|
1011
959
|
}
|
|
1012
960
|
}
|
|
1013
|
-
async
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
ws.send(JSON.stringify({ type: "file_tree", tree: [] }));
|
|
961
|
+
async openInVSCode(filename) {
|
|
962
|
+
const commands = ["code", "code-insiders", "codium"];
|
|
963
|
+
for (const cmd of commands) {
|
|
964
|
+
try {
|
|
965
|
+
await execAsync(`which ${cmd}`);
|
|
966
|
+
await execAsync(`${cmd} "${filename}"`);
|
|
1020
967
|
return;
|
|
968
|
+
} catch (error) {
|
|
969
|
+
continue;
|
|
1021
970
|
}
|
|
1022
|
-
const tree = index.entries.filter((e) => !e.path.includes("node_modules") && !e.path.startsWith(".")).map((e) => ({
|
|
1023
|
-
path: e.path,
|
|
1024
|
-
name: path14.basename(e.path),
|
|
1025
|
-
isDirectory: e.isDirectory,
|
|
1026
|
-
size: e.size
|
|
1027
|
-
})).slice(0, 500);
|
|
1028
|
-
ws.send(JSON.stringify({ type: "file_tree", tree }));
|
|
1029
|
-
} catch (error) {
|
|
1030
|
-
ws.send(JSON.stringify({ type: "error", content: error.message }));
|
|
1031
971
|
}
|
|
972
|
+
throw new Error("VS Code not found");
|
|
1032
973
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
const fullPath = path14.join(process.cwd(), filePath);
|
|
1036
|
-
if (!fullPath.startsWith(process.cwd())) {
|
|
1037
|
-
throw new Error("Access denied");
|
|
1038
|
-
}
|
|
1039
|
-
const content = await fs15.readFile(fullPath, "utf-8");
|
|
1040
|
-
ws.send(JSON.stringify({
|
|
1041
|
-
type: "file_content",
|
|
1042
|
-
path: filePath,
|
|
1043
|
-
content: content.slice(0, 1e4)
|
|
1044
|
-
}));
|
|
1045
|
-
} catch (error) {
|
|
1046
|
-
ws.send(JSON.stringify({ type: "error", content: error.message }));
|
|
1047
|
-
}
|
|
974
|
+
isPending() {
|
|
975
|
+
return this.pendingConfirmation !== null;
|
|
1048
976
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
type: "sessions_list",
|
|
1056
|
-
sessions: sessions.map((s) => ({
|
|
1057
|
-
id: s.id,
|
|
1058
|
-
name: s.name,
|
|
1059
|
-
workingDirectory: s.workingDirectory,
|
|
1060
|
-
messageCount: s.messages.length,
|
|
1061
|
-
lastAccessed: s.lastAccessed
|
|
1062
|
-
}))
|
|
1063
|
-
}));
|
|
1064
|
-
} catch (error) {
|
|
1065
|
-
ws.send(JSON.stringify({ type: "error", content: error.message }));
|
|
1066
|
-
}
|
|
977
|
+
resetSession() {
|
|
978
|
+
this.sessionFlags = {
|
|
979
|
+
fileOperations: false,
|
|
980
|
+
bashCommands: false,
|
|
981
|
+
allOperations: false
|
|
982
|
+
};
|
|
1067
983
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
const { getSessionManager: getSessionManager2 } = await Promise.resolve().then(() => (init_session_manager(), exports_session_manager));
|
|
1071
|
-
const sessionManager = getSessionManager2();
|
|
1072
|
-
const session = await sessionManager.switchSession(sessionId);
|
|
1073
|
-
if (session) {
|
|
1074
|
-
ws.send(JSON.stringify({
|
|
1075
|
-
type: "session_switched",
|
|
1076
|
-
session: {
|
|
1077
|
-
id: session.id,
|
|
1078
|
-
name: session.name,
|
|
1079
|
-
workingDirectory: session.workingDirectory,
|
|
1080
|
-
messages: session.messages
|
|
1081
|
-
}
|
|
1082
|
-
}));
|
|
1083
|
-
} else {
|
|
1084
|
-
throw new Error("Session not found");
|
|
1085
|
-
}
|
|
1086
|
-
} catch (error) {
|
|
1087
|
-
ws.send(JSON.stringify({ type: "error", content: error.message }));
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
async checkAndSendUpdateNotification(ws) {
|
|
1091
|
-
try {
|
|
1092
|
-
const pkg = await Promise.resolve().then(() => __toESM(require_package(), 1));
|
|
1093
|
-
const { getUpdateChecker: getUpdateChecker2 } = await Promise.resolve().then(() => (init_update_checker(), exports_update_checker));
|
|
1094
|
-
const updateChecker = getUpdateChecker2(pkg.version);
|
|
1095
|
-
const updateInfo = await updateChecker.checkForUpdates();
|
|
1096
|
-
if (updateInfo?.updateAvailable) {
|
|
1097
|
-
ws.send(JSON.stringify({
|
|
1098
|
-
type: "update_available",
|
|
1099
|
-
currentVersion: updateInfo.currentVersion,
|
|
1100
|
-
latestVersion: updateInfo.latestVersion
|
|
1101
|
-
}));
|
|
1102
|
-
}
|
|
1103
|
-
} catch (error) {}
|
|
1104
|
-
}
|
|
1105
|
-
async start() {
|
|
1106
|
-
return new Promise((resolve5, reject) => {
|
|
1107
|
-
this.httpServer.listen(this.port, this.hostname, () => {
|
|
1108
|
-
const url = `http://${this.hostname}:${this.port}`;
|
|
1109
|
-
console.log(`\uD83C\uDF10 Web interface available at ${url}`);
|
|
1110
|
-
resolve5();
|
|
1111
|
-
});
|
|
1112
|
-
this.httpServer.on("error", (error) => {
|
|
1113
|
-
reject(error);
|
|
1114
|
-
});
|
|
1115
|
-
});
|
|
1116
|
-
}
|
|
1117
|
-
async openBrowser() {
|
|
1118
|
-
const url = `http://${this.hostname}:${this.port}`;
|
|
1119
|
-
try {
|
|
1120
|
-
await open(url);
|
|
1121
|
-
console.log(`\uD83D\uDE80 Opened browser at ${url}`);
|
|
1122
|
-
} catch (error) {
|
|
1123
|
-
console.warn(`Could not open browser automatically. Please visit ${url}`);
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
stop() {
|
|
1127
|
-
this.clients.forEach((client) => {
|
|
1128
|
-
client.close();
|
|
1129
|
-
});
|
|
1130
|
-
this.wss.close();
|
|
1131
|
-
this.httpServer.close();
|
|
1132
|
-
console.log("\uD83D\uDED1 Web server stopped");
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
var __dirname = "/home/runner/work/super-agent-cli/super-agent-cli/src/web";
|
|
1136
|
-
var init_server = () => {};
|
|
1137
|
-
|
|
1138
|
-
// src/utils/confirmation-service.ts
|
|
1139
|
-
import { EventEmitter } from "events";
|
|
1140
|
-
import { exec } from "child_process";
|
|
1141
|
-
import { promisify } from "util";
|
|
1142
|
-
var execAsync = promisify(exec);
|
|
1143
|
-
|
|
1144
|
-
class ConfirmationService extends EventEmitter {
|
|
1145
|
-
static instance;
|
|
1146
|
-
skipConfirmationThisSession = false;
|
|
1147
|
-
pendingConfirmation = null;
|
|
1148
|
-
resolveConfirmation = null;
|
|
1149
|
-
sessionFlags = {
|
|
1150
|
-
fileOperations: false,
|
|
1151
|
-
bashCommands: false,
|
|
1152
|
-
allOperations: false
|
|
1153
|
-
};
|
|
1154
|
-
static getInstance() {
|
|
1155
|
-
if (!ConfirmationService.instance) {
|
|
1156
|
-
ConfirmationService.instance = new ConfirmationService;
|
|
1157
|
-
}
|
|
1158
|
-
return ConfirmationService.instance;
|
|
1159
|
-
}
|
|
1160
|
-
constructor() {
|
|
1161
|
-
super();
|
|
1162
|
-
}
|
|
1163
|
-
async requestConfirmation(options, operationType = "file") {
|
|
1164
|
-
if (this.sessionFlags.allOperations || operationType === "file" && this.sessionFlags.fileOperations || operationType === "bash" && this.sessionFlags.bashCommands) {
|
|
1165
|
-
return { confirmed: true };
|
|
1166
|
-
}
|
|
1167
|
-
if (options.showVSCodeOpen) {
|
|
1168
|
-
try {
|
|
1169
|
-
await this.openInVSCode(options.filename);
|
|
1170
|
-
} catch (error) {
|
|
1171
|
-
options.showVSCodeOpen = false;
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
this.pendingConfirmation = new Promise((resolve) => {
|
|
1175
|
-
this.resolveConfirmation = resolve;
|
|
1176
|
-
});
|
|
1177
|
-
setImmediate(() => {
|
|
1178
|
-
this.emit("confirmation-requested", options);
|
|
1179
|
-
});
|
|
1180
|
-
const result = await this.pendingConfirmation;
|
|
1181
|
-
if (result.dontAskAgain) {
|
|
1182
|
-
if (operationType === "file") {
|
|
1183
|
-
this.sessionFlags.fileOperations = true;
|
|
1184
|
-
} else if (operationType === "bash") {
|
|
1185
|
-
this.sessionFlags.bashCommands = true;
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
return result;
|
|
1189
|
-
}
|
|
1190
|
-
confirmOperation(confirmed, dontAskAgain) {
|
|
1191
|
-
if (this.resolveConfirmation) {
|
|
1192
|
-
this.resolveConfirmation({ confirmed, dontAskAgain });
|
|
1193
|
-
this.resolveConfirmation = null;
|
|
1194
|
-
this.pendingConfirmation = null;
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
rejectOperation(feedback) {
|
|
1198
|
-
if (this.resolveConfirmation) {
|
|
1199
|
-
this.resolveConfirmation({ confirmed: false, feedback });
|
|
1200
|
-
this.resolveConfirmation = null;
|
|
1201
|
-
this.pendingConfirmation = null;
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
async openInVSCode(filename) {
|
|
1205
|
-
const commands = ["code", "code-insiders", "codium"];
|
|
1206
|
-
for (const cmd of commands) {
|
|
1207
|
-
try {
|
|
1208
|
-
await execAsync(`which ${cmd}`);
|
|
1209
|
-
await execAsync(`${cmd} "${filename}"`);
|
|
1210
|
-
return;
|
|
1211
|
-
} catch (error) {
|
|
1212
|
-
continue;
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
|
-
throw new Error("VS Code not found");
|
|
1216
|
-
}
|
|
1217
|
-
isPending() {
|
|
1218
|
-
return this.pendingConfirmation !== null;
|
|
1219
|
-
}
|
|
1220
|
-
resetSession() {
|
|
1221
|
-
this.sessionFlags = {
|
|
1222
|
-
fileOperations: false,
|
|
1223
|
-
bashCommands: false,
|
|
1224
|
-
allOperations: false
|
|
1225
|
-
};
|
|
1226
|
-
}
|
|
1227
|
-
getSessionFlags() {
|
|
1228
|
-
return { ...this.sessionFlags };
|
|
984
|
+
getSessionFlags() {
|
|
985
|
+
return { ...this.sessionFlags };
|
|
1229
986
|
}
|
|
1230
987
|
setSessionFlag(flagType, value) {
|
|
1231
988
|
this.sessionFlags[flagType] = value;
|
|
@@ -8411,45 +8168,844 @@ function ChatInterface({
|
|
|
8411
8168
|
onApiKeySet: handleApiKeySet
|
|
8412
8169
|
}, undefined, false, undefined, this);
|
|
8413
8170
|
}
|
|
8414
|
-
return /* @__PURE__ */ jsxDEV16(ChatInterfaceWithAgent, {
|
|
8415
|
-
agent: currentAgent,
|
|
8416
|
-
initialMessage
|
|
8417
|
-
}, undefined, false, undefined, this);
|
|
8171
|
+
return /* @__PURE__ */ jsxDEV16(ChatInterfaceWithAgent, {
|
|
8172
|
+
agent: currentAgent,
|
|
8173
|
+
initialMessage
|
|
8174
|
+
}, undefined, false, undefined, this);
|
|
8175
|
+
}
|
|
8176
|
+
|
|
8177
|
+
// src/commands/web.ts
|
|
8178
|
+
init_settings_manager();
|
|
8179
|
+
|
|
8180
|
+
// src/web/server.ts
|
|
8181
|
+
import { createServer } from "http";
|
|
8182
|
+
import { WebSocketServer } from "ws";
|
|
8183
|
+
import * as fs15 from "fs-extra";
|
|
8184
|
+
import * as path14 from "path";
|
|
8185
|
+
import open from "open";
|
|
8186
|
+
import mime from "mime";
|
|
8187
|
+
var __dirname = "/home/runner/work/super-agent-cli/super-agent-cli/src/web";
|
|
8188
|
+
|
|
8189
|
+
class WebServer {
|
|
8190
|
+
httpServer;
|
|
8191
|
+
wss;
|
|
8192
|
+
agent;
|
|
8193
|
+
hostname;
|
|
8194
|
+
port;
|
|
8195
|
+
clients = new Set;
|
|
8196
|
+
constructor(options) {
|
|
8197
|
+
this.hostname = options.hostname || "localhost";
|
|
8198
|
+
this.port = options.port || 3000;
|
|
8199
|
+
this.agent = options.agent;
|
|
8200
|
+
this.httpServer = createServer((req, res) => {
|
|
8201
|
+
this.handleHttpRequest(req, res);
|
|
8202
|
+
});
|
|
8203
|
+
this.wss = new WebSocketServer({ server: this.httpServer });
|
|
8204
|
+
this.wss.on("connection", (ws) => {
|
|
8205
|
+
this.handleWebSocketConnection(ws);
|
|
8206
|
+
});
|
|
8207
|
+
}
|
|
8208
|
+
async handleHttpRequest(req, res) {
|
|
8209
|
+
const url = req.url || "/";
|
|
8210
|
+
const requestedPath = url === "/" ? "index.html" : url;
|
|
8211
|
+
const sanitizedPath = requestedPath.split("?")[0].split("#")[0];
|
|
8212
|
+
const clientDir = path14.join(__dirname, "../web/client");
|
|
8213
|
+
const absolutePath = path14.resolve(clientDir, sanitizedPath.substring(1));
|
|
8214
|
+
if (!absolutePath.startsWith(clientDir)) {
|
|
8215
|
+
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
8216
|
+
res.end("Forbidden");
|
|
8217
|
+
return;
|
|
8218
|
+
}
|
|
8219
|
+
try {
|
|
8220
|
+
if (await fs15.pathExists(absolutePath)) {
|
|
8221
|
+
const stat5 = await fs15.stat(absolutePath);
|
|
8222
|
+
let filePath = absolutePath;
|
|
8223
|
+
if (stat5.isDirectory()) {
|
|
8224
|
+
filePath = path14.join(absolutePath, "index.html");
|
|
8225
|
+
}
|
|
8226
|
+
const content = await fs15.readFile(filePath);
|
|
8227
|
+
const mimeType = mime.getType(filePath) || "application/octet-stream";
|
|
8228
|
+
res.writeHead(200, { "Content-Type": mimeType });
|
|
8229
|
+
res.end(content);
|
|
8230
|
+
} else {
|
|
8231
|
+
res.writeHead(404);
|
|
8232
|
+
res.end("Not Found");
|
|
8233
|
+
}
|
|
8234
|
+
} catch (error) {
|
|
8235
|
+
console.error("Error serving file:", error);
|
|
8236
|
+
res.writeHead(500);
|
|
8237
|
+
res.end("Internal Server Error");
|
|
8238
|
+
}
|
|
8239
|
+
}
|
|
8240
|
+
handleWebSocketConnection(ws) {
|
|
8241
|
+
this.clients.add(ws);
|
|
8242
|
+
console.log(`\uD83D\uDCE1 Web client connected (${this.clients.size} total)`);
|
|
8243
|
+
this.checkAndSendUpdateNotification(ws);
|
|
8244
|
+
ws.on("message", async (data) => {
|
|
8245
|
+
try {
|
|
8246
|
+
const message = JSON.parse(data.toString());
|
|
8247
|
+
if (message.type === "prompt") {
|
|
8248
|
+
await this.handlePrompt(message.content, ws);
|
|
8249
|
+
} else if (message.type === "get_file_tree") {
|
|
8250
|
+
await this.handleGetFileTree(ws);
|
|
8251
|
+
} else if (message.type === "get_file_content") {
|
|
8252
|
+
await this.handleGetFileContent(message.path, ws);
|
|
8253
|
+
} else if (message.type === "list_sessions") {
|
|
8254
|
+
await this.handleListSessions(ws);
|
|
8255
|
+
} else if (message.type === "switch_session") {
|
|
8256
|
+
await this.handleSwitchSession(message.sessionId, ws);
|
|
8257
|
+
}
|
|
8258
|
+
} catch (error) {
|
|
8259
|
+
console.error("WebSocket message error:", error);
|
|
8260
|
+
ws.send(JSON.stringify({ type: "error", content: "Invalid message format" }));
|
|
8261
|
+
}
|
|
8262
|
+
});
|
|
8263
|
+
ws.on("close", () => {
|
|
8264
|
+
this.clients.delete(ws);
|
|
8265
|
+
console.log(`\uD83D\uDCE1 Web client disconnected (${this.clients.size} remaining)`);
|
|
8266
|
+
});
|
|
8267
|
+
ws.on("error", (error) => {
|
|
8268
|
+
console.error("WebSocket error:", error);
|
|
8269
|
+
});
|
|
8270
|
+
}
|
|
8271
|
+
async handlePrompt(prompt, ws) {
|
|
8272
|
+
try {
|
|
8273
|
+
ws.send(JSON.stringify({ type: "user_message", content: prompt }));
|
|
8274
|
+
const entries = await this.agent.processUserMessage(prompt);
|
|
8275
|
+
for (const entry of entries) {
|
|
8276
|
+
if (entry.type === "assistant") {
|
|
8277
|
+
ws.send(JSON.stringify({
|
|
8278
|
+
type: "assistant_message",
|
|
8279
|
+
content: entry.content
|
|
8280
|
+
}));
|
|
8281
|
+
} else if (entry.type === "tool_call") {
|
|
8282
|
+
ws.send(JSON.stringify({
|
|
8283
|
+
type: "tool_call",
|
|
8284
|
+
tool: entry.toolCall?.function.name,
|
|
8285
|
+
content: "Executing..."
|
|
8286
|
+
}));
|
|
8287
|
+
} else if (entry.type === "tool_result") {
|
|
8288
|
+
ws.send(JSON.stringify({
|
|
8289
|
+
type: "tool_result",
|
|
8290
|
+
tool: entry.toolCall?.function.name,
|
|
8291
|
+
content: entry.content
|
|
8292
|
+
}));
|
|
8293
|
+
}
|
|
8294
|
+
}
|
|
8295
|
+
ws.send(JSON.stringify({ type: "done" }));
|
|
8296
|
+
} catch (error) {
|
|
8297
|
+
ws.send(JSON.stringify({
|
|
8298
|
+
type: "error",
|
|
8299
|
+
content: error.message
|
|
8300
|
+
}));
|
|
8301
|
+
}
|
|
8302
|
+
}
|
|
8303
|
+
async handleGetFileTree(ws) {
|
|
8304
|
+
try {
|
|
8305
|
+
const { getFileIndexer: getFileIndexer2 } = await Promise.resolve().then(() => (init_indexer(), exports_indexer));
|
|
8306
|
+
const indexer = getFileIndexer2();
|
|
8307
|
+
const index = indexer.getIndex();
|
|
8308
|
+
if (!index) {
|
|
8309
|
+
ws.send(JSON.stringify({ type: "file_tree", tree: [] }));
|
|
8310
|
+
return;
|
|
8311
|
+
}
|
|
8312
|
+
const tree = index.entries.filter((e) => !e.path.includes("node_modules") && !e.path.startsWith(".")).map((e) => ({
|
|
8313
|
+
path: e.path,
|
|
8314
|
+
name: path14.basename(e.path),
|
|
8315
|
+
isDirectory: e.isDirectory,
|
|
8316
|
+
size: e.size
|
|
8317
|
+
})).slice(0, 500);
|
|
8318
|
+
ws.send(JSON.stringify({ type: "file_tree", tree }));
|
|
8319
|
+
} catch (error) {
|
|
8320
|
+
ws.send(JSON.stringify({ type: "error", content: error.message }));
|
|
8321
|
+
}
|
|
8322
|
+
}
|
|
8323
|
+
async handleGetFileContent(filePath, ws) {
|
|
8324
|
+
try {
|
|
8325
|
+
const fullPath = path14.join(process.cwd(), filePath);
|
|
8326
|
+
if (!fullPath.startsWith(process.cwd())) {
|
|
8327
|
+
throw new Error("Access denied");
|
|
8328
|
+
}
|
|
8329
|
+
const content = await fs15.readFile(fullPath, "utf-8");
|
|
8330
|
+
ws.send(JSON.stringify({
|
|
8331
|
+
type: "file_content",
|
|
8332
|
+
path: filePath,
|
|
8333
|
+
content: content.slice(0, 1e4)
|
|
8334
|
+
}));
|
|
8335
|
+
} catch (error) {
|
|
8336
|
+
ws.send(JSON.stringify({ type: "error", content: error.message }));
|
|
8337
|
+
}
|
|
8338
|
+
}
|
|
8339
|
+
async handleListSessions(ws) {
|
|
8340
|
+
try {
|
|
8341
|
+
const { getSessionManager: getSessionManager2 } = await Promise.resolve().then(() => (init_session_manager(), exports_session_manager));
|
|
8342
|
+
const sessionManager = getSessionManager2();
|
|
8343
|
+
const sessions = await sessionManager.listSessions();
|
|
8344
|
+
ws.send(JSON.stringify({
|
|
8345
|
+
type: "sessions_list",
|
|
8346
|
+
sessions: sessions.map((s) => ({
|
|
8347
|
+
id: s.id,
|
|
8348
|
+
name: s.name,
|
|
8349
|
+
workingDirectory: s.workingDirectory,
|
|
8350
|
+
messageCount: s.messages.length,
|
|
8351
|
+
lastAccessed: s.lastAccessed
|
|
8352
|
+
}))
|
|
8353
|
+
}));
|
|
8354
|
+
} catch (error) {
|
|
8355
|
+
ws.send(JSON.stringify({ type: "error", content: error.message }));
|
|
8356
|
+
}
|
|
8357
|
+
}
|
|
8358
|
+
async handleSwitchSession(sessionId, ws) {
|
|
8359
|
+
try {
|
|
8360
|
+
const { getSessionManager: getSessionManager2 } = await Promise.resolve().then(() => (init_session_manager(), exports_session_manager));
|
|
8361
|
+
const sessionManager = getSessionManager2();
|
|
8362
|
+
const session = await sessionManager.switchSession(sessionId);
|
|
8363
|
+
if (session) {
|
|
8364
|
+
ws.send(JSON.stringify({
|
|
8365
|
+
type: "session_switched",
|
|
8366
|
+
session: {
|
|
8367
|
+
id: session.id,
|
|
8368
|
+
name: session.name,
|
|
8369
|
+
workingDirectory: session.workingDirectory,
|
|
8370
|
+
messages: session.messages
|
|
8371
|
+
}
|
|
8372
|
+
}));
|
|
8373
|
+
} else {
|
|
8374
|
+
throw new Error("Session not found");
|
|
8375
|
+
}
|
|
8376
|
+
} catch (error) {
|
|
8377
|
+
ws.send(JSON.stringify({ type: "error", content: error.message }));
|
|
8378
|
+
}
|
|
8379
|
+
}
|
|
8380
|
+
async checkAndSendUpdateNotification(ws) {
|
|
8381
|
+
try {
|
|
8382
|
+
const pkg = await Promise.resolve().then(() => __toESM(require_package(), 1));
|
|
8383
|
+
const { getUpdateChecker: getUpdateChecker2 } = await Promise.resolve().then(() => (init_update_checker(), exports_update_checker));
|
|
8384
|
+
const updateChecker = getUpdateChecker2(pkg.version);
|
|
8385
|
+
const updateInfo = await updateChecker.checkForUpdates();
|
|
8386
|
+
if (updateInfo?.updateAvailable) {
|
|
8387
|
+
ws.send(JSON.stringify({
|
|
8388
|
+
type: "update_available",
|
|
8389
|
+
currentVersion: updateInfo.currentVersion,
|
|
8390
|
+
latestVersion: updateInfo.latestVersion
|
|
8391
|
+
}));
|
|
8392
|
+
}
|
|
8393
|
+
} catch (error) {}
|
|
8394
|
+
}
|
|
8395
|
+
async start() {
|
|
8396
|
+
return new Promise((resolve5, reject) => {
|
|
8397
|
+
this.httpServer.listen(this.port, this.hostname, () => {
|
|
8398
|
+
const url = `http://${this.hostname}:${this.port}`;
|
|
8399
|
+
console.log(`\uD83C\uDF10 Web interface available at ${url}`);
|
|
8400
|
+
resolve5();
|
|
8401
|
+
});
|
|
8402
|
+
this.httpServer.on("error", (error) => {
|
|
8403
|
+
reject(error);
|
|
8404
|
+
});
|
|
8405
|
+
});
|
|
8406
|
+
}
|
|
8407
|
+
async openBrowser() {
|
|
8408
|
+
const url = `http://${this.hostname}:${this.port}`;
|
|
8409
|
+
try {
|
|
8410
|
+
await open(url);
|
|
8411
|
+
console.log(`\uD83D\uDE80 Opened browser at ${url}`);
|
|
8412
|
+
} catch (error) {
|
|
8413
|
+
console.warn(`Could not open browser automatically. Please visit ${url}`);
|
|
8414
|
+
}
|
|
8415
|
+
}
|
|
8416
|
+
stop() {
|
|
8417
|
+
this.clients.forEach((client) => {
|
|
8418
|
+
client.close();
|
|
8419
|
+
});
|
|
8420
|
+
this.wss.close();
|
|
8421
|
+
this.httpServer.close();
|
|
8422
|
+
console.log("\uD83D\uDED1 Web server stopped");
|
|
8423
|
+
}
|
|
8424
|
+
}
|
|
8425
|
+
|
|
8426
|
+
// src/commands/web.ts
|
|
8427
|
+
import { Command } from "commander";
|
|
8428
|
+
import chalk from "chalk";
|
|
8429
|
+
function createWebCommand() {
|
|
8430
|
+
const webCommand = new Command("web").description("Start the web interface").option("-p, --port <number>", "Port to run server on", "3000").option("--no-browser", "Do not open browser automatically").action(async (options) => {
|
|
8431
|
+
const port = parseInt(options.port);
|
|
8432
|
+
const settingsManager = getSettingsManager();
|
|
8433
|
+
const apiKey = settingsManager.getApiKey();
|
|
8434
|
+
const baseURL = settingsManager.getBaseURL() || "https://api.openai.com/v1";
|
|
8435
|
+
const model = settingsManager.getCurrentModel();
|
|
8436
|
+
if (!apiKey) {
|
|
8437
|
+
console.error(chalk.red("API Key not found. Please configure it first."));
|
|
8438
|
+
process.exit(1);
|
|
8439
|
+
}
|
|
8440
|
+
console.log(chalk.blue(`Starting web server on port ${port}...`));
|
|
8441
|
+
const agent = new SuperAgent(apiKey, baseURL, model);
|
|
8442
|
+
const server = new WebServer({
|
|
8443
|
+
port,
|
|
8444
|
+
agent,
|
|
8445
|
+
openBrowser: options.browser
|
|
8446
|
+
});
|
|
8447
|
+
try {
|
|
8448
|
+
await server.start();
|
|
8449
|
+
if (options.browser) {
|
|
8450
|
+
await server.openBrowser();
|
|
8451
|
+
}
|
|
8452
|
+
process.on("SIGINT", () => {
|
|
8453
|
+
console.log(chalk.yellow(`
|
|
8454
|
+
Stopping server...`));
|
|
8455
|
+
server.stop();
|
|
8456
|
+
process.exit(0);
|
|
8457
|
+
});
|
|
8458
|
+
} catch (error) {
|
|
8459
|
+
console.error(chalk.red(`Failed to start server: ${error.message}`));
|
|
8460
|
+
process.exit(1);
|
|
8461
|
+
}
|
|
8462
|
+
});
|
|
8463
|
+
return webCommand;
|
|
8464
|
+
}
|
|
8465
|
+
function createServeCommand() {
|
|
8466
|
+
const serveCommand = new Command("serve").description("Start the web interface and CLI together").option("-p, --port <number>", "Port to run server on", "3000").action(async (options) => {
|
|
8467
|
+
console.log(chalk.yellow("Serve mode is currently an alias for 'web' mode with background persistence capabilities."));
|
|
8468
|
+
const port = parseInt(options.port);
|
|
8469
|
+
const settingsManager = getSettingsManager();
|
|
8470
|
+
const apiKey = settingsManager.getApiKey();
|
|
8471
|
+
if (!apiKey) {
|
|
8472
|
+
console.error(chalk.red("API Key not found."));
|
|
8473
|
+
process.exit(1);
|
|
8474
|
+
}
|
|
8475
|
+
const agent = new SuperAgent(apiKey, settingsManager.getBaseURL() || "", settingsManager.getCurrentModel());
|
|
8476
|
+
const server = new WebServer({ port, agent, openBrowser: true });
|
|
8477
|
+
await server.start();
|
|
8478
|
+
await server.openBrowser();
|
|
8479
|
+
});
|
|
8480
|
+
return serveCommand;
|
|
8481
|
+
}
|
|
8482
|
+
|
|
8483
|
+
// src/commands/index-cmd.ts
|
|
8484
|
+
import { Command as Command2 } from "commander";
|
|
8485
|
+
import fs16 from "fs/promises";
|
|
8486
|
+
import ignore from "ignore";
|
|
8487
|
+
import chalk2 from "chalk";
|
|
8488
|
+
import path15 from "path";
|
|
8489
|
+
var DEFAULT_IGNORES = [
|
|
8490
|
+
"node_modules",
|
|
8491
|
+
".git",
|
|
8492
|
+
"dist",
|
|
8493
|
+
"build",
|
|
8494
|
+
"coverage",
|
|
8495
|
+
".env",
|
|
8496
|
+
"*.log",
|
|
8497
|
+
".DS_Store",
|
|
8498
|
+
"Thumbs.db"
|
|
8499
|
+
];
|
|
8500
|
+
function createIndexCommand() {
|
|
8501
|
+
const indexCommand = new Command2("index").description(" recursively index a directory and save to a file").argument("[directory]", "Directory to index", ".").option("-o, --output <file>", "Output file path (default: index.md)").option("--no-ignore", "Disable .gitignore respecting").option("-d, --depth <depth>", "Max depth to traverse", "10").action(async (directory, options) => {
|
|
8502
|
+
try {
|
|
8503
|
+
const rootDir = path15.resolve(directory);
|
|
8504
|
+
const outputFile2 = options.output ? path15.resolve(options.output) : path15.join(rootDir, "index.md");
|
|
8505
|
+
const maxDepth = parseInt(options.depth);
|
|
8506
|
+
console.log(chalk2.blue(`Indexing directory: ${rootDir}`));
|
|
8507
|
+
const ig = ignore().add(DEFAULT_IGNORES);
|
|
8508
|
+
if (options.ignore !== false) {
|
|
8509
|
+
try {
|
|
8510
|
+
const gitignorePath = path15.join(rootDir, ".gitignore");
|
|
8511
|
+
const gitignoreContent = await fs16.readFile(gitignorePath, "utf-8");
|
|
8512
|
+
ig.add(gitignoreContent);
|
|
8513
|
+
} catch (e) {}
|
|
8514
|
+
}
|
|
8515
|
+
let outputContent = `# Directory Index
|
|
8516
|
+
|
|
8517
|
+
Generated for: ${rootDir}
|
|
8518
|
+
Date: ${new Date().toISOString()}
|
|
8519
|
+
|
|
8520
|
+
`;
|
|
8521
|
+
outputContent += "## File Structure\n\n```\n";
|
|
8522
|
+
async function buildTree(currentPath, depth, prefix = "") {
|
|
8523
|
+
if (depth > maxDepth) {
|
|
8524
|
+
return;
|
|
8525
|
+
}
|
|
8526
|
+
const relativePath = path15.relative(rootDir, currentPath);
|
|
8527
|
+
if (relativePath && ig.ignores(relativePath)) {
|
|
8528
|
+
return;
|
|
8529
|
+
}
|
|
8530
|
+
const stats = await fs16.stat(currentPath);
|
|
8531
|
+
const isDir = stats.isDirectory();
|
|
8532
|
+
const name = path15.basename(currentPath);
|
|
8533
|
+
if (isDir) {
|
|
8534
|
+
if (relativePath) {
|
|
8535
|
+
outputContent += `${prefix}${name}/
|
|
8536
|
+
`;
|
|
8537
|
+
}
|
|
8538
|
+
const entries = await fs16.readdir(currentPath, {
|
|
8539
|
+
withFileTypes: true
|
|
8540
|
+
});
|
|
8541
|
+
const sortedEntries = entries.sort((a, b) => {
|
|
8542
|
+
if (a.isDirectory() && !b.isDirectory()) {
|
|
8543
|
+
return -1;
|
|
8544
|
+
}
|
|
8545
|
+
if (!a.isDirectory() && b.isDirectory()) {
|
|
8546
|
+
return 1;
|
|
8547
|
+
}
|
|
8548
|
+
return a.name.localeCompare(b.name);
|
|
8549
|
+
});
|
|
8550
|
+
for (let i = 0;i < sortedEntries.length; i++) {
|
|
8551
|
+
const entry = sortedEntries[i];
|
|
8552
|
+
const isLast = i === sortedEntries.length - 1;
|
|
8553
|
+
const newPrefix = relativePath ? prefix + " " : "";
|
|
8554
|
+
await buildTree(path15.join(currentPath, entry.name), depth + 1, newPrefix);
|
|
8555
|
+
}
|
|
8556
|
+
} else {
|
|
8557
|
+
outputContent += `${prefix}${name}
|
|
8558
|
+
`;
|
|
8559
|
+
}
|
|
8560
|
+
}
|
|
8561
|
+
const files = [];
|
|
8562
|
+
async function walk(dir, currentDepth) {
|
|
8563
|
+
if (currentDepth > maxDepth) {
|
|
8564
|
+
return;
|
|
8565
|
+
}
|
|
8566
|
+
const entries = await fs16.readdir(dir, { withFileTypes: true });
|
|
8567
|
+
for (const entry of entries) {
|
|
8568
|
+
const fullPath = path15.join(dir, entry.name);
|
|
8569
|
+
const relPath = path15.relative(rootDir, fullPath);
|
|
8570
|
+
if (ig.ignores(relPath)) {
|
|
8571
|
+
continue;
|
|
8572
|
+
}
|
|
8573
|
+
if (entry.isDirectory()) {
|
|
8574
|
+
await walk(fullPath, currentDepth + 1);
|
|
8575
|
+
} else {
|
|
8576
|
+
files.push(relPath);
|
|
8577
|
+
}
|
|
8578
|
+
}
|
|
8579
|
+
}
|
|
8580
|
+
await walk(rootDir, 0);
|
|
8581
|
+
console.log(chalk2.blue(`Found ${files.length} files.`));
|
|
8582
|
+
outputContent = `# Project Index: ${path15.basename(rootDir)}
|
|
8583
|
+
|
|
8584
|
+
`;
|
|
8585
|
+
outputContent += `Total Files: ${files.length}
|
|
8586
|
+
|
|
8587
|
+
`;
|
|
8588
|
+
outputContent += `## Files
|
|
8589
|
+
|
|
8590
|
+
`;
|
|
8591
|
+
for (const file of files) {
|
|
8592
|
+
outputContent += `### ${file}
|
|
8593
|
+
`;
|
|
8594
|
+
const stats = await fs16.stat(path15.join(rootDir, file));
|
|
8595
|
+
outputContent += `- Size: ${stats.size} bytes
|
|
8596
|
+
`;
|
|
8597
|
+
outputContent += `- Modified: ${stats.mtime.toISOString()}
|
|
8598
|
+
|
|
8599
|
+
`;
|
|
8600
|
+
}
|
|
8601
|
+
await fs16.writeFile(outputFile2, outputContent);
|
|
8602
|
+
console.log(chalk2.green(`✓ Index generated at: ${outputFile2}`));
|
|
8603
|
+
} catch (error) {
|
|
8604
|
+
console.error(chalk2.red(`Error indexing directory: ${error.message}`));
|
|
8605
|
+
process.exit(1);
|
|
8606
|
+
}
|
|
8607
|
+
});
|
|
8608
|
+
return indexCommand;
|
|
8609
|
+
}
|
|
8610
|
+
|
|
8611
|
+
// src/commands/plugins.ts
|
|
8612
|
+
init_settings_manager();
|
|
8613
|
+
import { Command as Command3 } from "commander";
|
|
8614
|
+
function createPluginsCommand() {
|
|
8615
|
+
const pluginsCommand = new Command3("plugins").description("Manage plugins for Super Agent CLI").argument("[action]", "Action to perform (list, install, uninstall)").argument("[target]", "Plugin name or path");
|
|
8616
|
+
pluginsCommand.command("list").description("List installed plugins").action(() => {
|
|
8617
|
+
const manager = getSettingsManager();
|
|
8618
|
+
const settings = manager.loadUserSettings();
|
|
8619
|
+
const plugins = settings.plugins || [];
|
|
8620
|
+
if (plugins.length === 0) {
|
|
8621
|
+
console.log("No plugins installed.");
|
|
8622
|
+
return;
|
|
8623
|
+
}
|
|
8624
|
+
console.log("Installed plugins:");
|
|
8625
|
+
plugins.forEach((p) => console.log(`- ${p}`));
|
|
8626
|
+
});
|
|
8627
|
+
pluginsCommand.command("install <path>").description("Install a plugin from a path, GitHub URL, or registry").action(async (path16) => {
|
|
8628
|
+
try {
|
|
8629
|
+
const manager = PluginManager.getInstance();
|
|
8630
|
+
console.log(`Installing plugin from: ${path16}...`);
|
|
8631
|
+
const installedPath = await manager.installPlugin(path16);
|
|
8632
|
+
console.log(`✅ Plugin installed successfully: ${installedPath}`);
|
|
8633
|
+
} catch (error) {
|
|
8634
|
+
console.error(`❌ Error installing plugin: ${error.message}`);
|
|
8635
|
+
process.exit(1);
|
|
8636
|
+
}
|
|
8637
|
+
});
|
|
8638
|
+
pluginsCommand.command("uninstall <path>").description("Uninstall a plugin").action(async (path16) => {
|
|
8639
|
+
try {
|
|
8640
|
+
const manager = PluginManager.getInstance();
|
|
8641
|
+
await manager.removePlugin(path16);
|
|
8642
|
+
console.log(`✅ Plugin uninstalled: ${path16}`);
|
|
8643
|
+
} catch (error) {
|
|
8644
|
+
console.error(`❌ Error uninstalling plugin: ${error.message}`);
|
|
8645
|
+
process.exit(1);
|
|
8646
|
+
}
|
|
8647
|
+
});
|
|
8648
|
+
return pluginsCommand;
|
|
8649
|
+
}
|
|
8650
|
+
|
|
8651
|
+
// src/commands/skills.ts
|
|
8652
|
+
init_settings_manager();
|
|
8653
|
+
|
|
8654
|
+
// src/skills/manager.ts
|
|
8655
|
+
init_settings_manager();
|
|
8656
|
+
import fs17 from "fs/promises";
|
|
8657
|
+
import path16 from "path";
|
|
8658
|
+
|
|
8659
|
+
class SkillsManager {
|
|
8660
|
+
static instance;
|
|
8661
|
+
skillsPath;
|
|
8662
|
+
constructor() {
|
|
8663
|
+
this.skillsPath = path16.join(getSettingsManager().getStorageDirectory(), "skills");
|
|
8664
|
+
}
|
|
8665
|
+
static getInstance() {
|
|
8666
|
+
if (!SkillsManager.instance) {
|
|
8667
|
+
SkillsManager.instance = new SkillsManager;
|
|
8668
|
+
}
|
|
8669
|
+
return SkillsManager.instance;
|
|
8670
|
+
}
|
|
8671
|
+
async ensureSkillsDirectory() {
|
|
8672
|
+
try {
|
|
8673
|
+
await fs17.mkdir(this.skillsPath, { recursive: true });
|
|
8674
|
+
} catch (error) {}
|
|
8675
|
+
}
|
|
8676
|
+
async listSkills() {
|
|
8677
|
+
await this.ensureSkillsDirectory();
|
|
8678
|
+
try {
|
|
8679
|
+
const files = await fs17.readdir(this.skillsPath);
|
|
8680
|
+
return files.filter((file) => file.endsWith(".ts") || file.endsWith(".js") || file.endsWith(".json")).map((file) => path16.parse(file).name);
|
|
8681
|
+
} catch (error) {
|
|
8682
|
+
return [];
|
|
8683
|
+
}
|
|
8684
|
+
}
|
|
8685
|
+
async getSkillPath(name) {
|
|
8686
|
+
const extensions = [".ts", ".js", ".json"];
|
|
8687
|
+
for (const ext of extensions) {
|
|
8688
|
+
const fullPath = path16.join(this.skillsPath, `${name}${ext}`);
|
|
8689
|
+
try {
|
|
8690
|
+
await fs17.access(fullPath);
|
|
8691
|
+
return fullPath;
|
|
8692
|
+
} catch {
|
|
8693
|
+
continue;
|
|
8694
|
+
}
|
|
8695
|
+
}
|
|
8696
|
+
throw new Error(`Skill '${name}' not found`);
|
|
8697
|
+
}
|
|
8698
|
+
async getSkillContent(name) {
|
|
8699
|
+
const skillPath = await this.getSkillPath(name);
|
|
8700
|
+
return await fs17.readFile(skillPath, "utf-8");
|
|
8701
|
+
}
|
|
8702
|
+
async createSkill(name, description, agent) {
|
|
8703
|
+
await this.ensureSkillsDirectory();
|
|
8704
|
+
const prompt = `Create a robust TypeScript skill for the Super Agent CLI named "${name}".
|
|
8705
|
+
|
|
8706
|
+
Description: ${description}
|
|
8707
|
+
|
|
8708
|
+
The skill should be a module that exports a default function or class that implements the desired functionality.
|
|
8709
|
+
It should valid standalone TypeScript code.
|
|
8710
|
+
Include comments explaining how it works.
|
|
8711
|
+
|
|
8712
|
+
Structure:
|
|
8713
|
+
\`\`\`typescript
|
|
8714
|
+
// ${name} skill
|
|
8715
|
+
export default async function(args: any) {
|
|
8716
|
+
// implementation
|
|
8717
|
+
}
|
|
8718
|
+
\`\`\`
|
|
8719
|
+
|
|
8720
|
+
Return ONLY the code block.`;
|
|
8721
|
+
const response = await agent.processUserMessage(prompt);
|
|
8722
|
+
let code = "";
|
|
8723
|
+
for (const entry of response) {
|
|
8724
|
+
if (entry.type === "assistant") {
|
|
8725
|
+
const match = entry.content.match(/```(?:typescript|ts)?\n([\s\S]*?)```/);
|
|
8726
|
+
if (match) {
|
|
8727
|
+
code = match[1];
|
|
8728
|
+
break;
|
|
8729
|
+
} else {
|
|
8730
|
+
code = entry.content;
|
|
8731
|
+
}
|
|
8732
|
+
}
|
|
8733
|
+
}
|
|
8734
|
+
if (!code) {
|
|
8735
|
+
throw new Error("Failed to generate skill code");
|
|
8736
|
+
}
|
|
8737
|
+
const filePath = path16.join(this.skillsPath, `${name}.ts`);
|
|
8738
|
+
await fs17.writeFile(filePath, code);
|
|
8739
|
+
}
|
|
8740
|
+
async deleteSkill(name) {
|
|
8741
|
+
try {
|
|
8742
|
+
const skillPath = await this.getSkillPath(name);
|
|
8743
|
+
await fs17.unlink(skillPath);
|
|
8744
|
+
} catch (error) {
|
|
8745
|
+
throw new Error(`Failed to delete skill '${name}': ${error.message}`);
|
|
8746
|
+
}
|
|
8747
|
+
}
|
|
8748
|
+
}
|
|
8749
|
+
|
|
8750
|
+
// src/commands/skills.ts
|
|
8751
|
+
import { Command as Command4 } from "commander";
|
|
8752
|
+
import inquirer from "inquirer";
|
|
8753
|
+
import chalk3 from "chalk";
|
|
8754
|
+
function createSkillsCommand() {
|
|
8755
|
+
const skillsCommand = new Command4("skills").description("Manage AI skills");
|
|
8756
|
+
skillsCommand.command("list").description("List available skills").action(async () => {
|
|
8757
|
+
const manager = SkillsManager.getInstance();
|
|
8758
|
+
const skills = await manager.listSkills();
|
|
8759
|
+
if (skills.length === 0) {
|
|
8760
|
+
console.log("No skills found.");
|
|
8761
|
+
} else {
|
|
8762
|
+
console.log("Available skills:");
|
|
8763
|
+
skills.forEach((skill) => console.log(`- ${skill}`));
|
|
8764
|
+
}
|
|
8765
|
+
});
|
|
8766
|
+
skillsCommand.command("create <name>").description("Create a new skill with AI assistance").option("-d, --description <description>", "Description of the skill").action(async (name, options) => {
|
|
8767
|
+
try {
|
|
8768
|
+
const manager = SkillsManager.getInstance();
|
|
8769
|
+
const settingsManager = getSettingsManager();
|
|
8770
|
+
let description = options.description;
|
|
8771
|
+
if (!description) {
|
|
8772
|
+
const answer = await inquirer.prompt([
|
|
8773
|
+
{
|
|
8774
|
+
type: "input",
|
|
8775
|
+
name: "description",
|
|
8776
|
+
message: "Describe what this skill should do:"
|
|
8777
|
+
}
|
|
8778
|
+
]);
|
|
8779
|
+
description = answer.description;
|
|
8780
|
+
}
|
|
8781
|
+
console.log(chalk3.blue(`Generating skill '${name}' based on description: "${description}"...`));
|
|
8782
|
+
const apiKey = settingsManager.getApiKey();
|
|
8783
|
+
const baseURL = settingsManager.getBaseURL();
|
|
8784
|
+
const model = settingsManager.getCurrentModel();
|
|
8785
|
+
if (!apiKey) {
|
|
8786
|
+
console.error(chalk3.red("API Key not found. Please configure it first."));
|
|
8787
|
+
return;
|
|
8788
|
+
}
|
|
8789
|
+
const agent = new SuperAgent(apiKey, baseURL, model);
|
|
8790
|
+
await manager.createSkill(name, description, agent);
|
|
8791
|
+
console.log(chalk3.green(`✓ Skill '${name}' created successfully.`));
|
|
8792
|
+
} catch (error) {
|
|
8793
|
+
console.error(chalk3.red(`Error creating skill: ${error.message}`));
|
|
8794
|
+
}
|
|
8795
|
+
});
|
|
8796
|
+
skillsCommand.command("delete <name>").description("Delete a skill").action(async (name) => {
|
|
8797
|
+
try {
|
|
8798
|
+
const manager = SkillsManager.getInstance();
|
|
8799
|
+
await manager.deleteSkill(name);
|
|
8800
|
+
console.log(chalk3.green(`✓ Skill '${name}' deleted.`));
|
|
8801
|
+
} catch (error) {
|
|
8802
|
+
console.error(chalk3.red(`Error deleting skill: ${error.message}`));
|
|
8803
|
+
}
|
|
8804
|
+
});
|
|
8805
|
+
return skillsCommand;
|
|
8806
|
+
}
|
|
8807
|
+
|
|
8808
|
+
// src/commands/agents.ts
|
|
8809
|
+
init_settings_manager();
|
|
8810
|
+
|
|
8811
|
+
// src/agents/manager.ts
|
|
8812
|
+
init_settings_manager();
|
|
8813
|
+
import fs18 from "fs/promises";
|
|
8814
|
+
import path17 from "path";
|
|
8815
|
+
|
|
8816
|
+
class AgentsManager {
|
|
8817
|
+
static instance;
|
|
8818
|
+
agentsPath;
|
|
8819
|
+
constructor() {
|
|
8820
|
+
this.agentsPath = path17.join(getSettingsManager().getStorageDirectory(), "agents");
|
|
8821
|
+
}
|
|
8822
|
+
static getInstance() {
|
|
8823
|
+
if (!AgentsManager.instance) {
|
|
8824
|
+
AgentsManager.instance = new AgentsManager;
|
|
8825
|
+
}
|
|
8826
|
+
return AgentsManager.instance;
|
|
8827
|
+
}
|
|
8828
|
+
async ensureAgentsDirectory() {
|
|
8829
|
+
try {
|
|
8830
|
+
await fs18.mkdir(this.agentsPath, { recursive: true });
|
|
8831
|
+
} catch (error) {}
|
|
8832
|
+
}
|
|
8833
|
+
async listAgents() {
|
|
8834
|
+
await this.ensureAgentsDirectory();
|
|
8835
|
+
try {
|
|
8836
|
+
const files = await fs18.readdir(this.agentsPath);
|
|
8837
|
+
const agents = [];
|
|
8838
|
+
for (const file of files) {
|
|
8839
|
+
if (file.endsWith(".json")) {
|
|
8840
|
+
try {
|
|
8841
|
+
const content = await fs18.readFile(path17.join(this.agentsPath, file), "utf-8");
|
|
8842
|
+
agents.push(JSON.parse(content));
|
|
8843
|
+
} catch (e) {}
|
|
8844
|
+
}
|
|
8845
|
+
}
|
|
8846
|
+
return agents;
|
|
8847
|
+
} catch (error) {
|
|
8848
|
+
return [];
|
|
8849
|
+
}
|
|
8850
|
+
}
|
|
8851
|
+
async getAgent(name) {
|
|
8852
|
+
try {
|
|
8853
|
+
const content = await fs18.readFile(path17.join(this.agentsPath, `${name}.json`), "utf-8");
|
|
8854
|
+
return JSON.parse(content);
|
|
8855
|
+
} catch (error) {
|
|
8856
|
+
return null;
|
|
8857
|
+
}
|
|
8858
|
+
}
|
|
8859
|
+
async createAgent(config) {
|
|
8860
|
+
await this.ensureAgentsDirectory();
|
|
8861
|
+
const filePath = path17.join(this.agentsPath, `${config.name}.json`);
|
|
8862
|
+
await fs18.writeFile(filePath, JSON.stringify(config, null, 2));
|
|
8863
|
+
}
|
|
8864
|
+
async generateAgent(name, description, agent) {
|
|
8865
|
+
const prompt = `Create a configuration for an AI agent named "${name}" based on this description: "${description}".
|
|
8866
|
+
|
|
8867
|
+
The configuration should be a JSON object matching this interface:
|
|
8868
|
+
interface AgentConfig {
|
|
8869
|
+
name: string;
|
|
8870
|
+
role: string;
|
|
8871
|
+
description: string;
|
|
8872
|
+
model?: string; // suggest a model if appropriate, or leave undefined
|
|
8873
|
+
tools?: string[]; // suggest relevant tools/skills names
|
|
8874
|
+
temperature?: number;
|
|
8875
|
+
systemPrompt?: string; // a detailed system prompt for this agent
|
|
8876
|
+
}
|
|
8877
|
+
|
|
8878
|
+
Return ONLY the JSON object.`;
|
|
8879
|
+
const response = await agent.processUserMessage(prompt);
|
|
8880
|
+
let jsonData = "";
|
|
8881
|
+
for (const entry of response) {
|
|
8882
|
+
if (entry.type === "assistant") {
|
|
8883
|
+
const match = entry.content.match(/```(?:json)?\n([\s\S]*?)```/);
|
|
8884
|
+
if (match) {
|
|
8885
|
+
jsonData = match[1];
|
|
8886
|
+
break;
|
|
8887
|
+
} else {
|
|
8888
|
+
if (entry.content.trim().startsWith("{")) {
|
|
8889
|
+
jsonData = entry.content;
|
|
8890
|
+
}
|
|
8891
|
+
}
|
|
8892
|
+
}
|
|
8893
|
+
}
|
|
8894
|
+
if (!jsonData) {
|
|
8895
|
+
throw new Error("Failed to generate agent configuration");
|
|
8896
|
+
}
|
|
8897
|
+
try {
|
|
8898
|
+
const config = JSON.parse(jsonData);
|
|
8899
|
+
config.name = name;
|
|
8900
|
+
await this.createAgent(config);
|
|
8901
|
+
} catch (e) {
|
|
8902
|
+
throw new Error(`Failed to parse generated agent config: ${e.message}`);
|
|
8903
|
+
}
|
|
8904
|
+
}
|
|
8905
|
+
async deleteAgent(name) {
|
|
8906
|
+
try {
|
|
8907
|
+
const filePath = path17.join(this.agentsPath, `${name}.json`);
|
|
8908
|
+
await fs18.unlink(filePath);
|
|
8909
|
+
} catch (error) {
|
|
8910
|
+
throw new Error(`Failed to delete agent '${name}'`);
|
|
8911
|
+
}
|
|
8912
|
+
}
|
|
8913
|
+
}
|
|
8914
|
+
|
|
8915
|
+
// src/commands/agents.ts
|
|
8916
|
+
import { Command as Command5 } from "commander";
|
|
8917
|
+
import inquirer2 from "inquirer";
|
|
8918
|
+
import chalk4 from "chalk";
|
|
8919
|
+
function createAgentsCommand() {
|
|
8920
|
+
const agentsCommand = new Command5("agents").description("Manage AI agents");
|
|
8921
|
+
agentsCommand.command("list").description("List available agents").action(async () => {
|
|
8922
|
+
const manager = AgentsManager.getInstance();
|
|
8923
|
+
const agents = await manager.listAgents();
|
|
8924
|
+
if (agents.length === 0) {
|
|
8925
|
+
console.log("No agents found.");
|
|
8926
|
+
} else {
|
|
8927
|
+
console.log("Available agents:");
|
|
8928
|
+
agents.forEach((agent) => {
|
|
8929
|
+
console.log(`- ${chalk4.bold(agent.name)} (${agent.role})`);
|
|
8930
|
+
console.log(` ${chalk4.dim(agent.description)}`);
|
|
8931
|
+
});
|
|
8932
|
+
}
|
|
8933
|
+
});
|
|
8934
|
+
agentsCommand.command("create <name>").description("Create a new agent with AI assistance").option("-d, --description <description>", "Description of the agent's role and purpose").action(async (name, options) => {
|
|
8935
|
+
try {
|
|
8936
|
+
const manager = AgentsManager.getInstance();
|
|
8937
|
+
const settingsManager = getSettingsManager();
|
|
8938
|
+
let description = options.description;
|
|
8939
|
+
if (!description) {
|
|
8940
|
+
const answer = await inquirer2.prompt([
|
|
8941
|
+
{
|
|
8942
|
+
type: "input",
|
|
8943
|
+
name: "description",
|
|
8944
|
+
message: "Describe the agent's role and purpose:"
|
|
8945
|
+
}
|
|
8946
|
+
]);
|
|
8947
|
+
description = answer.description;
|
|
8948
|
+
}
|
|
8949
|
+
console.log(chalk4.blue(`Generating agent configuration for '${name}'...`));
|
|
8950
|
+
const apiKey = settingsManager.getApiKey();
|
|
8951
|
+
const baseURL = settingsManager.getBaseURL();
|
|
8952
|
+
const model = settingsManager.getCurrentModel();
|
|
8953
|
+
if (!apiKey) {
|
|
8954
|
+
console.error(chalk4.red("API Key not found. Please configure it first."));
|
|
8955
|
+
return;
|
|
8956
|
+
}
|
|
8957
|
+
const agent = new SuperAgent(apiKey, baseURL, model);
|
|
8958
|
+
await manager.generateAgent(name, description, agent);
|
|
8959
|
+
console.log(chalk4.green(`✓ Agent '${name}' created successfully.`));
|
|
8960
|
+
} catch (error) {
|
|
8961
|
+
console.error(chalk4.red(`Error creating agent: ${error.message}`));
|
|
8962
|
+
}
|
|
8963
|
+
});
|
|
8964
|
+
agentsCommand.command("delete <name>").description("Delete an agent").action(async (name) => {
|
|
8965
|
+
try {
|
|
8966
|
+
const manager = AgentsManager.getInstance();
|
|
8967
|
+
await manager.deleteAgent(name);
|
|
8968
|
+
console.log(chalk4.green(`✓ Agent '${name}' deleted.`));
|
|
8969
|
+
} catch (error) {
|
|
8970
|
+
console.error(chalk4.red(`Error deleting agent: ${error.message}`));
|
|
8971
|
+
}
|
|
8972
|
+
});
|
|
8973
|
+
return agentsCommand;
|
|
8418
8974
|
}
|
|
8419
8975
|
|
|
8420
8976
|
// src/commands/mcp.ts
|
|
8421
8977
|
init_config();
|
|
8422
|
-
import { Command } from "commander";
|
|
8423
|
-
import
|
|
8978
|
+
import { Command as Command6 } from "commander";
|
|
8979
|
+
import chalk5 from "chalk";
|
|
8424
8980
|
function createMCPCommand() {
|
|
8425
|
-
const mcpCommand = new
|
|
8981
|
+
const mcpCommand = new Command6("mcp");
|
|
8426
8982
|
mcpCommand.description("Manage MCP (Model Context Protocol) servers");
|
|
8427
8983
|
mcpCommand.command("add <name>").description("Add an MCP server").option("-t, --transport <type>", "Transport type (stdio, http, sse, streamable_http)", "stdio").option("-c, --command <command>", "Command to run the server (for stdio transport)").option("-a, --args [args...]", "Arguments for the server command (for stdio transport)", []).option("-u, --url <url>", "URL for HTTP/SSE transport").option("-h, --headers [headers...]", "HTTP headers (key=value format)", []).option("-e, --env [env...]", "Environment variables (key=value format)", []).action(async (name, options) => {
|
|
8428
8984
|
try {
|
|
8429
8985
|
if (PREDEFINED_SERVERS[name]) {
|
|
8430
8986
|
const config2 = PREDEFINED_SERVERS[name];
|
|
8431
8987
|
addMCPServer(config2);
|
|
8432
|
-
console.log(
|
|
8988
|
+
console.log(chalk5.green(`✓ Added predefined MCP server: ${name}`));
|
|
8433
8989
|
const manager2 = getMCPManager();
|
|
8434
8990
|
await manager2.addServer(config2);
|
|
8435
|
-
console.log(
|
|
8991
|
+
console.log(chalk5.green(`✓ Connected to MCP server: ${name}`));
|
|
8436
8992
|
const tools2 = manager2.getTools().filter((t) => t.serverName === name);
|
|
8437
|
-
console.log(
|
|
8993
|
+
console.log(chalk5.blue(` Available tools: ${tools2.length}`));
|
|
8438
8994
|
return;
|
|
8439
8995
|
}
|
|
8440
8996
|
const transportType = options.transport.toLowerCase();
|
|
8441
8997
|
if (transportType === "stdio") {
|
|
8442
8998
|
if (!options.command) {
|
|
8443
|
-
console.error(
|
|
8999
|
+
console.error(chalk5.red("Error: --command is required for stdio transport"));
|
|
8444
9000
|
process.exit(1);
|
|
8445
9001
|
}
|
|
8446
9002
|
} else if (transportType === "http" || transportType === "sse" || transportType === "streamable_http") {
|
|
8447
9003
|
if (!options.url) {
|
|
8448
|
-
console.error(
|
|
9004
|
+
console.error(chalk5.red(`Error: --url is required for ${transportType} transport`));
|
|
8449
9005
|
process.exit(1);
|
|
8450
9006
|
}
|
|
8451
9007
|
} else {
|
|
8452
|
-
console.error(
|
|
9008
|
+
console.error(chalk5.red("Error: Transport type must be stdio, http, sse, or streamable_http"));
|
|
8453
9009
|
process.exit(1);
|
|
8454
9010
|
}
|
|
8455
9011
|
const env = {};
|
|
@@ -8478,14 +9034,14 @@ function createMCPCommand() {
|
|
|
8478
9034
|
}
|
|
8479
9035
|
};
|
|
8480
9036
|
addMCPServer(config);
|
|
8481
|
-
console.log(
|
|
9037
|
+
console.log(chalk5.green(`✓ Added MCP server: ${name}`));
|
|
8482
9038
|
const manager = getMCPManager();
|
|
8483
9039
|
await manager.addServer(config);
|
|
8484
|
-
console.log(
|
|
9040
|
+
console.log(chalk5.green(`✓ Connected to MCP server: ${name}`));
|
|
8485
9041
|
const tools = manager.getTools().filter((t) => t.serverName === name);
|
|
8486
|
-
console.log(
|
|
9042
|
+
console.log(chalk5.blue(` Available tools: ${tools.length}`));
|
|
8487
9043
|
} catch (error) {
|
|
8488
|
-
console.error(
|
|
9044
|
+
console.error(chalk5.red(`Error adding MCP server: ${error.message}`));
|
|
8489
9045
|
process.exit(1);
|
|
8490
9046
|
}
|
|
8491
9047
|
});
|
|
@@ -8495,7 +9051,7 @@ function createMCPCommand() {
|
|
|
8495
9051
|
try {
|
|
8496
9052
|
config = JSON.parse(jsonConfig);
|
|
8497
9053
|
} catch (error) {
|
|
8498
|
-
console.error(
|
|
9054
|
+
console.error(chalk5.red("Error: Invalid JSON configuration"));
|
|
8499
9055
|
process.exit(1);
|
|
8500
9056
|
}
|
|
8501
9057
|
const serverConfig = {
|
|
@@ -8520,14 +9076,14 @@ function createMCPCommand() {
|
|
|
8520
9076
|
}
|
|
8521
9077
|
}
|
|
8522
9078
|
addMCPServer(serverConfig);
|
|
8523
|
-
console.log(
|
|
9079
|
+
console.log(chalk5.green(`✓ Added MCP server: ${name}`));
|
|
8524
9080
|
const manager = getMCPManager();
|
|
8525
9081
|
await manager.addServer(serverConfig);
|
|
8526
|
-
console.log(
|
|
9082
|
+
console.log(chalk5.green(`✓ Connected to MCP server: ${name}`));
|
|
8527
9083
|
const tools = manager.getTools().filter((t) => t.serverName === name);
|
|
8528
|
-
console.log(
|
|
9084
|
+
console.log(chalk5.blue(` Available tools: ${tools.length}`));
|
|
8529
9085
|
} catch (error) {
|
|
8530
|
-
console.error(
|
|
9086
|
+
console.error(chalk5.red(`Error adding MCP server: ${error.message}`));
|
|
8531
9087
|
process.exit(1);
|
|
8532
9088
|
}
|
|
8533
9089
|
});
|
|
@@ -8536,9 +9092,9 @@ function createMCPCommand() {
|
|
|
8536
9092
|
const manager = getMCPManager();
|
|
8537
9093
|
await manager.removeServer(name);
|
|
8538
9094
|
removeMCPServer(name);
|
|
8539
|
-
console.log(
|
|
9095
|
+
console.log(chalk5.green(`✓ Removed MCP server: ${name}`));
|
|
8540
9096
|
} catch (error) {
|
|
8541
|
-
console.error(
|
|
9097
|
+
console.error(chalk5.red(`Error removing MCP server: ${error.message}`));
|
|
8542
9098
|
process.exit(1);
|
|
8543
9099
|
}
|
|
8544
9100
|
});
|
|
@@ -8546,15 +9102,15 @@ function createMCPCommand() {
|
|
|
8546
9102
|
const config = loadMCPConfig();
|
|
8547
9103
|
const manager = getMCPManager();
|
|
8548
9104
|
if (config.servers.length === 0) {
|
|
8549
|
-
console.log(
|
|
9105
|
+
console.log(chalk5.yellow("No MCP servers configured"));
|
|
8550
9106
|
return;
|
|
8551
9107
|
}
|
|
8552
|
-
console.log(
|
|
9108
|
+
console.log(chalk5.bold("Configured MCP servers:"));
|
|
8553
9109
|
console.log();
|
|
8554
9110
|
for (const server of config.servers) {
|
|
8555
9111
|
const isConnected = manager.getServers().includes(server.name);
|
|
8556
|
-
const status = isConnected ?
|
|
8557
|
-
console.log(`${
|
|
9112
|
+
const status = isConnected ? chalk5.green("✓ Connected") : chalk5.red("✗ Disconnected");
|
|
9113
|
+
console.log(`${chalk5.bold(server.name)}: ${status}`);
|
|
8558
9114
|
if (server.transport) {
|
|
8559
9115
|
console.log(` Transport: ${server.transport.type}`);
|
|
8560
9116
|
if (server.transport.type === "stdio") {
|
|
@@ -8587,15 +9143,15 @@ function createMCPCommand() {
|
|
|
8587
9143
|
const config = loadMCPConfig();
|
|
8588
9144
|
const serverConfig = config.servers.find((s) => s.name === name);
|
|
8589
9145
|
if (!serverConfig) {
|
|
8590
|
-
console.error(
|
|
9146
|
+
console.error(chalk5.red(`Server ${name} not found`));
|
|
8591
9147
|
process.exit(1);
|
|
8592
9148
|
}
|
|
8593
|
-
console.log(
|
|
9149
|
+
console.log(chalk5.blue(`Testing connection to ${name}...`));
|
|
8594
9150
|
const manager = getMCPManager();
|
|
8595
9151
|
await manager.addServer(serverConfig);
|
|
8596
9152
|
const tools = manager.getTools().filter((t) => t.serverName === name);
|
|
8597
|
-
console.log(
|
|
8598
|
-
console.log(
|
|
9153
|
+
console.log(chalk5.green(`✓ Successfully connected to ${name}`));
|
|
9154
|
+
console.log(chalk5.blue(` Available tools: ${tools.length}`));
|
|
8599
9155
|
if (tools.length > 0) {
|
|
8600
9156
|
console.log(" Tools:");
|
|
8601
9157
|
tools.forEach((tool) => {
|
|
@@ -8604,82 +9160,44 @@ function createMCPCommand() {
|
|
|
8604
9160
|
});
|
|
8605
9161
|
}
|
|
8606
9162
|
} catch (error) {
|
|
8607
|
-
console.error(
|
|
9163
|
+
console.error(chalk5.red(`✗ Failed to connect to ${name}: ${error.message}`));
|
|
8608
9164
|
process.exit(1);
|
|
8609
9165
|
}
|
|
8610
9166
|
});
|
|
8611
9167
|
return mcpCommand;
|
|
8612
9168
|
}
|
|
8613
9169
|
|
|
8614
|
-
// src/
|
|
8615
|
-
|
|
8616
|
-
import {
|
|
8617
|
-
|
|
8618
|
-
import { render } from "ink";
|
|
8619
|
-
import React4 from "react";
|
|
8620
|
-
dotenv.config();
|
|
8621
|
-
process.on("SIGTERM", () => {
|
|
8622
|
-
if (process.stdin.isTTY && process.stdin.setRawMode) {
|
|
8623
|
-
try {
|
|
8624
|
-
process.stdin.setRawMode(false);
|
|
8625
|
-
} catch (e) {}
|
|
8626
|
-
}
|
|
8627
|
-
console.log(`
|
|
8628
|
-
Gracefully shutting down...`);
|
|
8629
|
-
process.exit(0);
|
|
8630
|
-
});
|
|
8631
|
-
process.on("uncaughtException", (error) => {
|
|
8632
|
-
console.error("Uncaught exception:", error);
|
|
8633
|
-
process.exit(1);
|
|
8634
|
-
});
|
|
8635
|
-
process.on("unhandledRejection", (reason, promise) => {
|
|
8636
|
-
console.error("Unhandled rejection at:", promise, "reason:", reason);
|
|
8637
|
-
process.exit(1);
|
|
8638
|
-
});
|
|
8639
|
-
function ensureUserSettingsDirectory() {
|
|
8640
|
-
try {
|
|
8641
|
-
const manager = getSettingsManager();
|
|
8642
|
-
manager.loadUserSettings();
|
|
8643
|
-
} catch (error) {}
|
|
8644
|
-
}
|
|
8645
|
-
function loadApiKey() {
|
|
9170
|
+
// src/commands/git.ts
|
|
9171
|
+
init_settings_manager();
|
|
9172
|
+
import { Command as Command7 } from "commander";
|
|
9173
|
+
async function loadApiKey() {
|
|
8646
9174
|
const manager = getSettingsManager();
|
|
8647
9175
|
return manager.getApiKey();
|
|
8648
9176
|
}
|
|
8649
|
-
function loadBaseURL() {
|
|
9177
|
+
async function loadBaseURL() {
|
|
8650
9178
|
const manager = getSettingsManager();
|
|
8651
9179
|
return manager.getBaseURL();
|
|
8652
9180
|
}
|
|
9181
|
+
async function loadModel() {
|
|
9182
|
+
const manager = getSettingsManager();
|
|
9183
|
+
return process.env.SUPER_AGENT_MODEL || manager.getCurrentModel();
|
|
9184
|
+
}
|
|
8653
9185
|
async function saveCommandLineSettings(apiKey, baseURL) {
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
9186
|
+
if (!apiKey && !baseURL) {
|
|
9187
|
+
return;
|
|
9188
|
+
}
|
|
9189
|
+
const manager = getSettingsManager();
|
|
9190
|
+
const settings = manager.loadUserSettings();
|
|
9191
|
+
const activeProviderId = settings.active_provider;
|
|
9192
|
+
if (settings.providers[activeProviderId]) {
|
|
8661
9193
|
if (apiKey) {
|
|
8662
9194
|
settings.providers[activeProviderId].api_key = apiKey;
|
|
8663
|
-
console.log(`✅ API key saved for provider '${activeProviderId}' to ~/.super-agent/settings.json`);
|
|
8664
9195
|
}
|
|
8665
9196
|
if (baseURL) {
|
|
8666
9197
|
settings.providers[activeProviderId].base_url = baseURL;
|
|
8667
|
-
console.log(`✅ Base URL saved for provider '${activeProviderId}' to ~/.super-agent/settings.json`);
|
|
8668
9198
|
}
|
|
8669
9199
|
manager.saveUserSettings(settings);
|
|
8670
|
-
} catch (error) {
|
|
8671
|
-
console.warn("⚠️ Could not save settings to file:", error instanceof Error ? error.message : "Unknown error");
|
|
8672
|
-
}
|
|
8673
|
-
}
|
|
8674
|
-
function loadModel() {
|
|
8675
|
-
let model = process.env.SUPER_AGENT_MODEL;
|
|
8676
|
-
if (!model) {
|
|
8677
|
-
try {
|
|
8678
|
-
const manager = getSettingsManager();
|
|
8679
|
-
model = manager.getCurrentModel();
|
|
8680
|
-
} catch (error) {}
|
|
8681
9200
|
}
|
|
8682
|
-
return model;
|
|
8683
9201
|
}
|
|
8684
9202
|
async function handleCommitAndPushHeadless(apiKey, baseURL, model, maxToolRounds) {
|
|
8685
9203
|
try {
|
|
@@ -8754,6 +9272,120 @@ Respond with ONLY the commit message, no additional text.`;
|
|
|
8754
9272
|
process.exit(1);
|
|
8755
9273
|
}
|
|
8756
9274
|
}
|
|
9275
|
+
function createGitCommand() {
|
|
9276
|
+
const gitCommand = new Command7("git").description("Git operations with AI assistance");
|
|
9277
|
+
gitCommand.command("commit-and-push").description("Generate AI commit message and push to remote").option("-d, --directory <dir>", "set working directory", process.cwd()).option("-k, --api-key <key>", "Super Agent API key (or set SUPER_AGENT_API_KEY env var)").option("-u, --base-url <url>", "Super Agent API base URL (or set SUPER_AGENT_BASE_URL env var)").option("-m, --model <model>", "AI model to use (e.g., GLM-4.7) (or set SUPER_AGENT_MODEL env var)").option("--max-tool-rounds <rounds>", "maximum number of tool execution rounds (default: 400)", "400").action(async (options) => {
|
|
9278
|
+
if (options.directory) {
|
|
9279
|
+
try {
|
|
9280
|
+
process.chdir(options.directory);
|
|
9281
|
+
} catch (error) {
|
|
9282
|
+
console.error(`Error changing directory to ${options.directory}:`, error.message);
|
|
9283
|
+
process.exit(1);
|
|
9284
|
+
}
|
|
9285
|
+
}
|
|
9286
|
+
try {
|
|
9287
|
+
const apiKey = options.apiKey || await loadApiKey();
|
|
9288
|
+
const baseURL = options.baseUrl || await loadBaseURL();
|
|
9289
|
+
const model = options.model || await loadModel();
|
|
9290
|
+
const maxToolRounds = parseInt(options.maxToolRounds) || 400;
|
|
9291
|
+
if (!apiKey) {
|
|
9292
|
+
console.error("❌ Error: API key required for git operations. Set SUPER_AGENT_API_KEY environment variable.");
|
|
9293
|
+
process.exit(1);
|
|
9294
|
+
}
|
|
9295
|
+
if (options.apiKey || options.baseUrl) {
|
|
9296
|
+
await saveCommandLineSettings(options.apiKey, options.baseUrl);
|
|
9297
|
+
}
|
|
9298
|
+
await handleCommitAndPushHeadless(apiKey, baseURL, model, maxToolRounds);
|
|
9299
|
+
} catch (error) {
|
|
9300
|
+
console.error("❌ Error during git commit-and-push:", error.message);
|
|
9301
|
+
process.exit(1);
|
|
9302
|
+
}
|
|
9303
|
+
});
|
|
9304
|
+
return gitCommand;
|
|
9305
|
+
}
|
|
9306
|
+
|
|
9307
|
+
// src/commands/index.ts
|
|
9308
|
+
function registerCommands(program) {
|
|
9309
|
+
program.addCommand(createMCPCommand());
|
|
9310
|
+
program.addCommand(createPluginsCommand());
|
|
9311
|
+
program.addCommand(createGitCommand());
|
|
9312
|
+
program.addCommand(createWebCommand());
|
|
9313
|
+
program.addCommand(createServeCommand());
|
|
9314
|
+
program.addCommand(createSkillsCommand());
|
|
9315
|
+
program.addCommand(createAgentsCommand());
|
|
9316
|
+
program.addCommand(createIndexCommand());
|
|
9317
|
+
}
|
|
9318
|
+
|
|
9319
|
+
// src/index.ts
|
|
9320
|
+
var import__package = __toESM(require_package(), 1);
|
|
9321
|
+
import { program } from "commander";
|
|
9322
|
+
import * as dotenv from "dotenv";
|
|
9323
|
+
import { render } from "ink";
|
|
9324
|
+
import React4 from "react";
|
|
9325
|
+
dotenv.config();
|
|
9326
|
+
process.on("SIGTERM", () => {
|
|
9327
|
+
if (process.stdin.isTTY && process.stdin.setRawMode) {
|
|
9328
|
+
try {
|
|
9329
|
+
process.stdin.setRawMode(false);
|
|
9330
|
+
} catch (e) {}
|
|
9331
|
+
}
|
|
9332
|
+
console.log(`
|
|
9333
|
+
Gracefully shutting down...`);
|
|
9334
|
+
process.exit(0);
|
|
9335
|
+
});
|
|
9336
|
+
process.on("uncaughtException", (error) => {
|
|
9337
|
+
console.error("Uncaught exception:", error);
|
|
9338
|
+
process.exit(1);
|
|
9339
|
+
});
|
|
9340
|
+
process.on("unhandledRejection", (reason, promise) => {
|
|
9341
|
+
console.error("Unhandled rejection at:", promise, "reason:", reason);
|
|
9342
|
+
process.exit(1);
|
|
9343
|
+
});
|
|
9344
|
+
function ensureUserSettingsDirectory() {
|
|
9345
|
+
try {
|
|
9346
|
+
const manager = getSettingsManager();
|
|
9347
|
+
manager.loadUserSettings();
|
|
9348
|
+
} catch (error) {}
|
|
9349
|
+
}
|
|
9350
|
+
function loadApiKey2() {
|
|
9351
|
+
const manager = getSettingsManager();
|
|
9352
|
+
return manager.getApiKey();
|
|
9353
|
+
}
|
|
9354
|
+
function loadBaseURL2() {
|
|
9355
|
+
const manager = getSettingsManager();
|
|
9356
|
+
return manager.getBaseURL();
|
|
9357
|
+
}
|
|
9358
|
+
async function saveCommandLineSettings2(apiKey, baseURL) {
|
|
9359
|
+
try {
|
|
9360
|
+
const manager = getSettingsManager();
|
|
9361
|
+
const settings = manager.loadUserSettings();
|
|
9362
|
+
const activeProviderId = settings.active_provider;
|
|
9363
|
+
if (!settings.providers[activeProviderId]) {
|
|
9364
|
+
return;
|
|
9365
|
+
}
|
|
9366
|
+
if (apiKey) {
|
|
9367
|
+
settings.providers[activeProviderId].api_key = apiKey;
|
|
9368
|
+
console.log(`✅ API key saved for provider '${activeProviderId}' to ~/.super-agent/settings.json`);
|
|
9369
|
+
}
|
|
9370
|
+
if (baseURL) {
|
|
9371
|
+
settings.providers[activeProviderId].base_url = baseURL;
|
|
9372
|
+
console.log(`✅ Base URL saved for provider '${activeProviderId}' to ~/.super-agent/settings.json`);
|
|
9373
|
+
}
|
|
9374
|
+
manager.saveUserSettings(settings);
|
|
9375
|
+
} catch (error) {
|
|
9376
|
+
console.warn("⚠️ Could not save settings to file:", error instanceof Error ? error.message : "Unknown error");
|
|
9377
|
+
}
|
|
9378
|
+
}
|
|
9379
|
+
function loadModel2() {
|
|
9380
|
+
let model = process.env.SUPER_AGENT_MODEL;
|
|
9381
|
+
if (!model) {
|
|
9382
|
+
try {
|
|
9383
|
+
const manager = getSettingsManager();
|
|
9384
|
+
model = manager.getCurrentModel();
|
|
9385
|
+
} catch (error) {}
|
|
9386
|
+
}
|
|
9387
|
+
return model;
|
|
9388
|
+
}
|
|
8757
9389
|
async function processPromptHeadless(prompt, apiKey, baseURL, model, maxToolRounds) {
|
|
8758
9390
|
try {
|
|
8759
9391
|
const agent = new SuperAgent(apiKey, baseURL, model, maxToolRounds);
|
|
@@ -8818,9 +9450,9 @@ program.name("super-agent").description("A conversational AI CLI tool powered by
|
|
|
8818
9450
|
}
|
|
8819
9451
|
}
|
|
8820
9452
|
try {
|
|
8821
|
-
const apiKey = options.apiKey ||
|
|
8822
|
-
const baseURL = options.baseUrl ||
|
|
8823
|
-
const model = options.model ||
|
|
9453
|
+
const apiKey = options.apiKey || loadApiKey2();
|
|
9454
|
+
const baseURL = options.baseUrl || loadBaseURL2();
|
|
9455
|
+
const model = options.model || loadModel2();
|
|
8824
9456
|
const maxToolRounds = parseInt(options.maxToolRounds) || 400;
|
|
8825
9457
|
if (!apiKey && !options.prompt) {
|
|
8826
9458
|
console.warn("⚠️ Warning: No API key found. Some features may not work. Use /config or set SUPER_AGENT_API_KEY.");
|
|
@@ -8829,7 +9461,7 @@ program.name("super-agent").description("A conversational AI CLI tool powered by
|
|
|
8829
9461
|
process.exit(1);
|
|
8830
9462
|
}
|
|
8831
9463
|
if (options.apiKey || options.baseUrl) {
|
|
8832
|
-
await
|
|
9464
|
+
await saveCommandLineSettings2(options.apiKey, options.baseUrl);
|
|
8833
9465
|
}
|
|
8834
9466
|
if (options.prompt) {
|
|
8835
9467
|
await processPromptHeadless(options.prompt, apiKey, baseURL, model, maxToolRounds);
|
|
@@ -8857,141 +9489,6 @@ program.name("super-agent").description("A conversational AI CLI tool powered by
|
|
|
8857
9489
|
process.exit(1);
|
|
8858
9490
|
}
|
|
8859
9491
|
});
|
|
8860
|
-
|
|
8861
|
-
|
|
8862
|
-
console.log(import__package.default.description);
|
|
8863
|
-
console.log(`
|
|
8864
|
-
Maintained by: ` + import__package.default.author);
|
|
8865
|
-
console.log(`
|
|
8866
|
-
Source code: ` + import__package.default.repository.url);
|
|
8867
|
-
console.log(`
|
|
8868
|
-
Funding: ` + import__package.default.funding);
|
|
8869
|
-
process.exit(0);
|
|
8870
|
-
});
|
|
8871
|
-
var pluginsCommand = program.command("plugins list/install/uninstall <name> / <path>").description("Manage plugins for Super Agent CLI");
|
|
8872
|
-
pluginsCommand.command("list").description("List installed plugins").action(() => {
|
|
8873
|
-
console.log("List installed plugins");
|
|
8874
|
-
process.exit(0);
|
|
8875
|
-
});
|
|
8876
|
-
pluginsCommand.command("install <name> / <path>").description("Install a plugin").action(() => {
|
|
8877
|
-
console.log("Install a plugin");
|
|
8878
|
-
process.exit(0);
|
|
8879
|
-
});
|
|
8880
|
-
pluginsCommand.command("uninstall <name>").description("Uninstall a plugin").action(() => {
|
|
8881
|
-
console.log("Uninstall a plugin");
|
|
8882
|
-
process.exit(0);
|
|
8883
|
-
});
|
|
8884
|
-
var gitCommand = program.command("git").description("Git operations with AI assistance");
|
|
8885
|
-
gitCommand.command("commit-and-push").description("Generate AI commit message and push to remote").option("-d, --directory <dir>", "set working directory", process.cwd()).option("-k, --api-key <key>", "Super Agent API key (or set SUPER_AGENT_API_KEY env var)").option("-u, --base-url <url>", "Super Agent API base URL (or set SUPER_AGENT_BASE_URL env var)").option("-m, --model <model>", "AI model to use (e.g., GLM-4.7) (or set SUPER_AGENT_MODEL env var)").option("--max-tool-rounds <rounds>", "maximum number of tool execution rounds (default: 400)", "400").action(async (options) => {
|
|
8886
|
-
if (options.directory) {
|
|
8887
|
-
try {
|
|
8888
|
-
process.chdir(options.directory);
|
|
8889
|
-
} catch (error) {
|
|
8890
|
-
console.error(`Error changing directory to ${options.directory}:`, error.message);
|
|
8891
|
-
process.exit(1);
|
|
8892
|
-
}
|
|
8893
|
-
}
|
|
8894
|
-
try {
|
|
8895
|
-
const apiKey = options.apiKey || loadApiKey();
|
|
8896
|
-
const baseURL = options.baseUrl || loadBaseURL();
|
|
8897
|
-
const model = options.model || loadModel();
|
|
8898
|
-
const maxToolRounds = parseInt(options.maxToolRounds) || 400;
|
|
8899
|
-
if (!apiKey) {
|
|
8900
|
-
console.error("❌ Error: API key required for git operations. Set SUPER_AGENT_API_KEY environment variable.");
|
|
8901
|
-
process.exit(1);
|
|
8902
|
-
}
|
|
8903
|
-
if (options.apiKey || options.baseUrl) {
|
|
8904
|
-
await saveCommandLineSettings(options.apiKey, options.baseUrl);
|
|
8905
|
-
}
|
|
8906
|
-
await handleCommitAndPushHeadless(apiKey, baseURL, model, maxToolRounds);
|
|
8907
|
-
} catch (error) {
|
|
8908
|
-
console.error("❌ Error during git commit-and-push:", error.message);
|
|
8909
|
-
process.exit(1);
|
|
8910
|
-
}
|
|
8911
|
-
});
|
|
8912
|
-
var webCommand = program.command("web").description("Start web server interface").option("--hostname <hostname>", "Server hostname", "localhost").option("--port <port>", "Server port", "3000").option("-d, --directory <dir>", "set working directory", process.cwd()).option("-k, --api-key <key>", "Super Agent API key (or set SUPER_AGENT_API_KEY env var)").option("-u, --base-url <url>", "Super Agent API base URL (or set SUPER_AGENT_BASE_URL env var)").option("-m, --model <model>", "AI model to use (e.g., GLM-4.7) (or set SUPER_AGENT_MODEL env var)").option("--max-tool-rounds <rounds>", "maximum number of tool execution rounds (default: 400)", "400").option("--no-open", "Don't open browser automatically").action(async (options) => {
|
|
8913
|
-
if (options.directory) {
|
|
8914
|
-
try {
|
|
8915
|
-
process.chdir(options.directory);
|
|
8916
|
-
} catch (error) {
|
|
8917
|
-
console.error(`Error changing directory to ${options.directory}:`, error.message);
|
|
8918
|
-
process.exit(1);
|
|
8919
|
-
}
|
|
8920
|
-
}
|
|
8921
|
-
try {
|
|
8922
|
-
const { WebServer: WebServer2 } = await Promise.resolve().then(() => (init_server(), exports_server));
|
|
8923
|
-
const apiKey = options.apiKey || loadApiKey();
|
|
8924
|
-
const baseURL = options.baseUrl || loadBaseURL();
|
|
8925
|
-
const model = options.model || loadModel();
|
|
8926
|
-
const maxToolRounds = parseInt(options.maxToolRounds) || 400;
|
|
8927
|
-
if (!apiKey) {
|
|
8928
|
-
console.warn("⚠️ Warning: No API key found. Web interface may not work properly.");
|
|
8929
|
-
}
|
|
8930
|
-
if (options.apiKey || options.baseUrl) {
|
|
8931
|
-
await saveCommandLineSettings(options.apiKey, options.baseUrl);
|
|
8932
|
-
}
|
|
8933
|
-
const agent = new SuperAgent(apiKey || "", baseURL, model, maxToolRounds);
|
|
8934
|
-
const server = new WebServer2({
|
|
8935
|
-
hostname: options.hostname,
|
|
8936
|
-
port: parseInt(options.port),
|
|
8937
|
-
agent
|
|
8938
|
-
});
|
|
8939
|
-
await server.start();
|
|
8940
|
-
if (options.open !== false) {
|
|
8941
|
-
await server.openBrowser();
|
|
8942
|
-
}
|
|
8943
|
-
process.on("SIGINT", () => {
|
|
8944
|
-
server.stop();
|
|
8945
|
-
process.exit(0);
|
|
8946
|
-
});
|
|
8947
|
-
} catch (error) {
|
|
8948
|
-
console.error("❌ Error starting web server:", error.message);
|
|
8949
|
-
process.exit(1);
|
|
8950
|
-
}
|
|
8951
|
-
});
|
|
8952
|
-
var serveCommand = program.command("serve").description("Run both CLI and web interface simultaneously").option("--hostname <hostname>", "Server hostname", "localhost").option("--port <port>", "Server port", "3000").option("-d, --directory <dir>", "set working directory", process.cwd()).option("-k, --api-key <key>", "Super Agent API key (or set SUPER_AGENT_API_KEY env var)").option("-u, --base-url <url>", "Super Agent API base URL (or set SUPER_AGENT_BASE_URL env var)").option("-m, --model <model>", "AI model to use (e.g., GLM-4.7) (or set SUPER_AGENT_MODEL env var)").option("--max-tool-rounds <rounds>", "maximum number of tool execution rounds (default: 400)", "400").option("--no-open", "Don't open browser automatically").action(async (options) => {
|
|
8953
|
-
if (options.directory) {
|
|
8954
|
-
try {
|
|
8955
|
-
process.chdir(options.directory);
|
|
8956
|
-
} catch (error) {
|
|
8957
|
-
console.error(`Error changing directory to ${options.directory}:`, error.message);
|
|
8958
|
-
process.exit(1);
|
|
8959
|
-
}
|
|
8960
|
-
}
|
|
8961
|
-
try {
|
|
8962
|
-
const { WebServer: WebServer2 } = await Promise.resolve().then(() => (init_server(), exports_server));
|
|
8963
|
-
const apiKey = options.apiKey || loadApiKey();
|
|
8964
|
-
const baseURL = options.baseUrl || loadBaseURL();
|
|
8965
|
-
const model = options.model || loadModel();
|
|
8966
|
-
const maxToolRounds = parseInt(options.maxToolRounds) || 400;
|
|
8967
|
-
if (!apiKey) {
|
|
8968
|
-
console.warn("⚠️ Warning: No API key found. Some features may not work.");
|
|
8969
|
-
}
|
|
8970
|
-
if (options.apiKey || options.baseUrl) {
|
|
8971
|
-
await saveCommandLineSettings(options.apiKey, options.baseUrl);
|
|
8972
|
-
}
|
|
8973
|
-
const agent = new SuperAgent(apiKey || "", baseURL, model, maxToolRounds);
|
|
8974
|
-
const server = new WebServer2({
|
|
8975
|
-
hostname: options.hostname,
|
|
8976
|
-
port: parseInt(options.port),
|
|
8977
|
-
agent
|
|
8978
|
-
});
|
|
8979
|
-
await server.start();
|
|
8980
|
-
if (options.open !== false) {
|
|
8981
|
-
await server.openBrowser();
|
|
8982
|
-
}
|
|
8983
|
-
console.log(`\uD83E\uDD16 Starting CLI interface...
|
|
8984
|
-
`);
|
|
8985
|
-
ensureUserSettingsDirectory();
|
|
8986
|
-
render(React4.createElement(ChatInterface, { agent }));
|
|
8987
|
-
process.on("SIGINT", () => {
|
|
8988
|
-
server.stop();
|
|
8989
|
-
process.exit(0);
|
|
8990
|
-
});
|
|
8991
|
-
} catch (error) {
|
|
8992
|
-
console.error("❌ Error starting serve mode:", error.message);
|
|
8993
|
-
process.exit(1);
|
|
8994
|
-
}
|
|
8995
|
-
});
|
|
8996
|
-
program.addCommand(createMCPCommand());
|
|
9492
|
+
registerCommands(program);
|
|
9493
|
+
program.parse();
|
|
8997
9494
|
program.parse();
|