@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 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.60",
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 fs13 from "fs-extra";
675
- import * as path12 from "path";
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 = path12.join(settingsManager.getStorageDirectory(), "update-cache.json");
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 fs13.pathExists(this.cacheFile)) {
696
- const cache = await fs13.readJson(this.cacheFile);
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 fs13.outputJson(this.cacheFile, info);
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/session-manager.ts
777
- var exports_session_manager = {};
778
- __export(exports_session_manager, {
779
- getSessionManager: () => getSessionManager,
780
- SessionManager: () => SessionManager
863
+ // src/utils/banner.ts
864
+ var exports_banner = {};
865
+ __export(exports_banner, {
866
+ HELP_BANNER: () => HELP_BANNER,
867
+ BANNER: () => BANNER
781
868
  });
782
- import * as fs14 from "fs-extra";
783
- import * as path13 from "path";
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
- class SessionManager {
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
- sessionsDir;
788
- currentSession = null;
789
- constructor() {
790
- const settingsManager = getSettingsManager();
791
- this.sessionsDir = path13.join(settingsManager.getStorageDirectory(), "sessions");
792
- fs14.ensureDirSync(this.sessionsDir);
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 (!SessionManager.instance) {
796
- SessionManager.instance = new SessionManager;
912
+ if (!ConfirmationService.instance) {
913
+ ConfirmationService.instance = new ConfirmationService;
797
914
  }
798
- return SessionManager.instance;
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
- async saveSession(session) {
832
- const sessionFile = this.getSessionFilePath(session.id);
833
- await fs14.outputJson(sessionFile, session, { spaces: 2 });
917
+ constructor() {
918
+ super();
834
919
  }
835
- async addMessage(message) {
836
- if (!this.currentSession) {
837
- throw new Error("No active session");
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
- this.currentSession.messages.push(message);
840
- this.currentSession.lastAccessed = Date.now();
841
- await this.saveSession(this.currentSession);
842
- }
843
- async listSessions() {
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
- sessions.sort((a, b) => b.lastAccessed - a.lastAccessed);
855
- return sessions;
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
- this.wss = new WebSocketServer({ server: this.httpServer });
914
- this.wss.on("connection", (ws) => {
915
- this.handleWebSocketConnection(ws);
934
+ setImmediate(() => {
935
+ this.emit("confirmation-requested", options);
916
936
  });
917
- }
918
- async handleHttpRequest(req, res) {
919
- const url = req.url || "/";
920
- const requestedPath = url === "/" ? "index.html" : url;
921
- const sanitizedPath = requestedPath.split("?")[0].split("#")[0];
922
- const clientDir = path14.join(__dirname, "../web/client");
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
- handleWebSocketConnection(ws) {
951
- this.clients.add(ws);
952
- console.log(`\uD83D\uDCE1 Web client connected (${this.clients.size} total)`);
953
- this.checkAndSendUpdateNotification(ws);
954
- ws.on("message", async (data) => {
955
- try {
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
- async handlePrompt(prompt, ws) {
982
- try {
983
- ws.send(JSON.stringify({ type: "user_message", content: prompt }));
984
- const entries = await this.agent.processUserMessage(prompt);
985
- for (const entry of entries) {
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 handleGetFileTree(ws) {
1014
- try {
1015
- const { getFileIndexer: getFileIndexer2 } = await Promise.resolve().then(() => (init_indexer(), exports_indexer));
1016
- const indexer = getFileIndexer2();
1017
- const index = indexer.getIndex();
1018
- if (!index) {
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
- async handleGetFileContent(filePath, ws) {
1034
- try {
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
- async handleListSessions(ws) {
1050
- try {
1051
- const { getSessionManager: getSessionManager2 } = await Promise.resolve().then(() => (init_session_manager(), exports_session_manager));
1052
- const sessionManager = getSessionManager2();
1053
- const sessions = await sessionManager.listSessions();
1054
- ws.send(JSON.stringify({
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
- async handleSwitchSession(sessionId, ws) {
1069
- try {
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 chalk from "chalk";
8978
+ import { Command as Command6 } from "commander";
8979
+ import chalk5 from "chalk";
8424
8980
  function createMCPCommand() {
8425
- const mcpCommand = new Command("mcp");
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(chalk.green(`✓ Added predefined MCP server: ${name}`));
8988
+ console.log(chalk5.green(`✓ Added predefined MCP server: ${name}`));
8433
8989
  const manager2 = getMCPManager();
8434
8990
  await manager2.addServer(config2);
8435
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
8991
+ console.log(chalk5.green(`✓ Connected to MCP server: ${name}`));
8436
8992
  const tools2 = manager2.getTools().filter((t) => t.serverName === name);
8437
- console.log(chalk.blue(` Available tools: ${tools2.length}`));
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(chalk.red("Error: --command is required for stdio transport"));
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(chalk.red(`Error: --url is required for ${transportType} transport`));
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(chalk.red("Error: Transport type must be stdio, http, sse, or streamable_http"));
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(chalk.green(`✓ Added MCP server: ${name}`));
9037
+ console.log(chalk5.green(`✓ Added MCP server: ${name}`));
8482
9038
  const manager = getMCPManager();
8483
9039
  await manager.addServer(config);
8484
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
9040
+ console.log(chalk5.green(`✓ Connected to MCP server: ${name}`));
8485
9041
  const tools = manager.getTools().filter((t) => t.serverName === name);
8486
- console.log(chalk.blue(` Available tools: ${tools.length}`));
9042
+ console.log(chalk5.blue(` Available tools: ${tools.length}`));
8487
9043
  } catch (error) {
8488
- console.error(chalk.red(`Error adding MCP server: ${error.message}`));
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(chalk.red("Error: Invalid JSON configuration"));
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(chalk.green(`✓ Added MCP server: ${name}`));
9079
+ console.log(chalk5.green(`✓ Added MCP server: ${name}`));
8524
9080
  const manager = getMCPManager();
8525
9081
  await manager.addServer(serverConfig);
8526
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
9082
+ console.log(chalk5.green(`✓ Connected to MCP server: ${name}`));
8527
9083
  const tools = manager.getTools().filter((t) => t.serverName === name);
8528
- console.log(chalk.blue(` Available tools: ${tools.length}`));
9084
+ console.log(chalk5.blue(` Available tools: ${tools.length}`));
8529
9085
  } catch (error) {
8530
- console.error(chalk.red(`Error adding MCP server: ${error.message}`));
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(chalk.green(`✓ Removed MCP server: ${name}`));
9095
+ console.log(chalk5.green(`✓ Removed MCP server: ${name}`));
8540
9096
  } catch (error) {
8541
- console.error(chalk.red(`Error removing MCP server: ${error.message}`));
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(chalk.yellow("No MCP servers configured"));
9105
+ console.log(chalk5.yellow("No MCP servers configured"));
8550
9106
  return;
8551
9107
  }
8552
- console.log(chalk.bold("Configured MCP servers:"));
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 ? chalk.green("✓ Connected") : chalk.red("✗ Disconnected");
8557
- console.log(`${chalk.bold(server.name)}: ${status}`);
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(chalk.red(`Server ${name} not found`));
9146
+ console.error(chalk5.red(`Server ${name} not found`));
8591
9147
  process.exit(1);
8592
9148
  }
8593
- console.log(chalk.blue(`Testing connection to ${name}...`));
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(chalk.green(`✓ Successfully connected to ${name}`));
8598
- console.log(chalk.blue(` Available tools: ${tools.length}`));
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(chalk.red(`✗ Failed to connect to ${name}: ${error.message}`));
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/index.ts
8615
- var import__package = __toESM(require_package(), 1);
8616
- import { program } from "commander";
8617
- import * as dotenv from "dotenv";
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
- try {
8655
- const manager = getSettingsManager();
8656
- const settings = manager.loadUserSettings();
8657
- const activeProviderId = settings.active_provider;
8658
- if (!settings.providers[activeProviderId]) {
8659
- return;
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 || loadApiKey();
8822
- const baseURL = options.baseUrl || loadBaseURL();
8823
- const model = options.model || loadModel();
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 saveCommandLineSettings(options.apiKey, options.baseUrl);
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
- var aboutCommand = program.command("about").description("Show information about the Super Agent CLI").action(() => {
8861
- console.log(import__package.default.name + " " + import__package.default.version);
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();