@involvex/super-agent-cli 0.0.61 → 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.61",
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",
@@ -592,6 +703,7 @@ var require_package = __commonJS((exports, module) => {
592
703
  dependencies: {
593
704
  "@google/generative-ai": "^0.24.1",
594
705
  "@modelcontextprotocol/sdk": "^1.25.3",
706
+ "@types/mime": "^4.0.0",
595
707
  axios: "^1.13.4",
596
708
  cfonts: "^3.3.1",
597
709
  chalk: "^5.6.2",
@@ -600,7 +712,9 @@ var require_package = __commonJS((exports, module) => {
600
712
  dotenv: "^17.2.3",
601
713
  enquirer: "^2.4.1",
602
714
  "fs-extra": "^11.3.3",
715
+ ignore: "^7.0.5",
603
716
  ink: "^6.6.0",
717
+ inquirer: "^13.2.2",
604
718
  marked: "^17.0.1",
605
719
  "marked-terminal": "^7.3.0",
606
720
  mime: "^4.1.0",
@@ -638,46 +752,14 @@ var require_package = __commonJS((exports, module) => {
638
752
  };
639
753
  });
640
754
 
641
- // src/utils/banner.ts
642
- var exports_banner = {};
643
- __export(exports_banner, {
644
- HELP_BANNER: () => HELP_BANNER,
645
- BANNER: () => BANNER
646
- });
647
- var BANNER = `
648
- ╔═══════════════════════════════════════════════════════════════╗
649
- ║ ║
650
- ║ ███████╗██╗ ██╗██████╗ ███████╗██████╗ ║
651
- ║ ██╔════╝██║ ██║██╔══██╗██╔════╝██╔══██╗ ║
652
- ║ ███████╗██║ ██║██████╔╝█████╗ ██████╔╝ ║
653
- ║ ╚════██║██║ ██║██╔═══╝ ██╔══╝ ██╔══██╗ ║
654
- ║ ███████║╚██████╔╝██║ ███████╗██║ ██║ ║
655
- ║ ╚══════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ║
656
- ║ ║
657
- ║ █████╗ ██████╗ ███████╗███╗ ██╗████████╗ ║
658
- ║ ██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝ ║
659
- ║ ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ║
660
- ║ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ║
661
- ║ ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ║
662
- ║ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ║
663
- ║ ║
664
- ║ \uD83E\uDD16 AI-Powered Terminal Assistant ║
665
- ║ ║
666
- ╚═══════════════════════════════════════════════════════════════╝
667
- `, HELP_BANNER = `
668
- ╔═══════════════════════════════════════════╗
669
- ║ \uD83E\uDD16 SUPER AGENT - Help & Usage ║
670
- ╚═══════════════════════════════════════════╝
671
- `;
672
-
673
755
  // src/utils/update-checker.ts
674
756
  var exports_update_checker = {};
675
757
  __export(exports_update_checker, {
676
758
  getUpdateChecker: () => getUpdateChecker,
677
759
  UpdateChecker: () => UpdateChecker
678
760
  });
679
- import * as fs13 from "fs-extra";
680
- import * as path12 from "path";
761
+ import * as fs14 from "fs-extra";
762
+ import * as path13 from "path";
681
763
  import axios3 from "axios";
682
764
 
683
765
  class UpdateChecker {
@@ -686,7 +768,7 @@ class UpdateChecker {
686
768
  currentVersion;
687
769
  constructor(currentVersion) {
688
770
  const settingsManager = getSettingsManager();
689
- this.cacheFile = path12.join(settingsManager.getStorageDirectory(), "update-cache.json");
771
+ this.cacheFile = path13.join(settingsManager.getStorageDirectory(), "update-cache.json");
690
772
  this.currentVersion = currentVersion;
691
773
  }
692
774
  static getInstance(currentVersion) {
@@ -697,8 +779,8 @@ class UpdateChecker {
697
779
  }
698
780
  async loadCache() {
699
781
  try {
700
- if (await fs13.pathExists(this.cacheFile)) {
701
- const cache = await fs13.readJson(this.cacheFile);
782
+ if (await fs14.pathExists(this.cacheFile)) {
783
+ const cache = await fs14.readJson(this.cacheFile);
702
784
  const now = Date.now();
703
785
  if (cache.lastChecked && now - cache.lastChecked < CACHE_DURATION) {
704
786
  return cache;
@@ -709,7 +791,7 @@ class UpdateChecker {
709
791
  }
710
792
  async saveCache(info) {
711
793
  try {
712
- await fs13.outputJson(this.cacheFile, info);
794
+ await fs14.outputJson(this.cacheFile, info);
713
795
  } catch (error) {}
714
796
  }
715
797
  compareVersions(v1, v2) {
@@ -778,459 +860,129 @@ var init_update_checker = __esm(() => {
778
860
  CACHE_DURATION = 24 * 60 * 60 * 1000;
779
861
  });
780
862
 
781
- // src/utils/session-manager.ts
782
- var exports_session_manager = {};
783
- __export(exports_session_manager, {
784
- getSessionManager: () => getSessionManager,
785
- SessionManager: () => SessionManager
863
+ // src/utils/banner.ts
864
+ var exports_banner = {};
865
+ __export(exports_banner, {
866
+ HELP_BANNER: () => HELP_BANNER,
867
+ BANNER: () => BANNER
786
868
  });
787
- import * as fs14 from "fs-extra";
788
- 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
+ `;
789
894
 
790
- 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 {
791
902
  static instance;
792
- sessionsDir;
793
- currentSession = null;
794
- constructor() {
795
- const settingsManager = getSettingsManager();
796
- this.sessionsDir = path13.join(settingsManager.getStorageDirectory(), "sessions");
797
- fs14.ensureDirSync(this.sessionsDir);
798
- }
903
+ skipConfirmationThisSession = false;
904
+ pendingConfirmation = null;
905
+ resolveConfirmation = null;
906
+ sessionFlags = {
907
+ fileOperations: false,
908
+ bashCommands: false,
909
+ allOperations: false
910
+ };
799
911
  static getInstance() {
800
- if (!SessionManager.instance) {
801
- SessionManager.instance = new SessionManager;
912
+ if (!ConfirmationService.instance) {
913
+ ConfirmationService.instance = new ConfirmationService;
802
914
  }
803
- return SessionManager.instance;
804
- }
805
- generateSessionId(workingDir) {
806
- const normalized = path13.normalize(workingDir).toLowerCase();
807
- return Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
808
- }
809
- getSessionFilePath(sessionId) {
810
- return path13.join(this.sessionsDir, `${sessionId}.json`);
811
- }
812
- async getOrCreateSession(workingDirectory, name) {
813
- const sessionId = this.generateSessionId(workingDirectory);
814
- const sessionFile = this.getSessionFilePath(sessionId);
815
- try {
816
- if (await fs14.pathExists(sessionFile)) {
817
- const session = await fs14.readJson(sessionFile);
818
- session.lastAccessed = Date.now();
819
- this.currentSession = session;
820
- await this.saveSession(session);
821
- return session;
822
- }
823
- } catch (error) {}
824
- const newSession = {
825
- id: sessionId,
826
- workingDirectory,
827
- name: name || path13.basename(workingDirectory),
828
- messages: [],
829
- lastAccessed: Date.now(),
830
- createdAt: Date.now()
831
- };
832
- this.currentSession = newSession;
833
- await this.saveSession(newSession);
834
- return newSession;
915
+ return ConfirmationService.instance;
835
916
  }
836
- async saveSession(session) {
837
- const sessionFile = this.getSessionFilePath(session.id);
838
- await fs14.outputJson(sessionFile, session, { spaces: 2 });
917
+ constructor() {
918
+ super();
839
919
  }
840
- async addMessage(message) {
841
- if (!this.currentSession) {
842
- 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 };
843
923
  }
844
- this.currentSession.messages.push(message);
845
- this.currentSession.lastAccessed = Date.now();
846
- await this.saveSession(this.currentSession);
847
- }
848
- async listSessions() {
849
- const sessionFiles = await fs14.readdir(this.sessionsDir);
850
- const sessions = [];
851
- for (const file of sessionFiles) {
852
- if (file.endsWith(".json")) {
853
- try {
854
- const session = await fs14.readJson(path13.join(this.sessionsDir, file));
855
- sessions.push(session);
856
- } catch (error) {}
924
+ if (options.showVSCodeOpen) {
925
+ try {
926
+ await this.openInVSCode(options.filename);
927
+ } catch (error) {
928
+ options.showVSCodeOpen = false;
857
929
  }
858
930
  }
859
- sessions.sort((a, b) => b.lastAccessed - a.lastAccessed);
860
- return sessions;
861
- }
862
- async deleteSession(sessionId) {
863
- const sessionFile = this.getSessionFilePath(sessionId);
864
- if (await fs14.pathExists(sessionFile)) {
865
- await fs14.remove(sessionFile);
866
- }
867
- }
868
- getCurrentSession() {
869
- return this.currentSession;
870
- }
871
- async switchSession(sessionId) {
872
- const sessionFile = this.getSessionFilePath(sessionId);
873
- try {
874
- if (await fs14.pathExists(sessionFile)) {
875
- const session = await fs14.readJson(sessionFile);
876
- session.lastAccessed = Date.now();
877
- this.currentSession = session;
878
- await this.saveSession(session);
879
- return session;
880
- }
881
- } catch (error) {}
882
- return null;
883
- }
884
- }
885
- function getSessionManager() {
886
- return SessionManager.getInstance();
887
- }
888
- var init_session_manager = __esm(() => {
889
- init_settings_manager();
890
- });
891
-
892
- // src/web/server.ts
893
- var exports_server = {};
894
- __export(exports_server, {
895
- WebServer: () => WebServer
896
- });
897
- import { createServer } from "http";
898
- import { WebSocketServer } from "ws";
899
- import * as fs15 from "fs-extra";
900
- import * as path14 from "path";
901
- import open from "open";
902
- import mime from "mime";
903
-
904
- class WebServer {
905
- httpServer;
906
- wss;
907
- agent;
908
- hostname;
909
- port;
910
- clients = new Set;
911
- constructor(options) {
912
- this.hostname = options.hostname || "localhost";
913
- this.port = options.port || 3000;
914
- this.agent = options.agent;
915
- this.httpServer = createServer((req, res) => {
916
- this.handleHttpRequest(req, res);
931
+ this.pendingConfirmation = new Promise((resolve) => {
932
+ this.resolveConfirmation = resolve;
917
933
  });
918
- this.wss = new WebSocketServer({ server: this.httpServer });
919
- this.wss.on("connection", (ws) => {
920
- this.handleWebSocketConnection(ws);
934
+ setImmediate(() => {
935
+ this.emit("confirmation-requested", options);
921
936
  });
922
- }
923
- async handleHttpRequest(req, res) {
924
- const url = req.url || "/";
925
- const requestedPath = url === "/" ? "index.html" : url;
926
- const sanitizedPath = requestedPath.split("?")[0].split("#")[0];
927
- const clientDir = path14.join(__dirname, "../web/client");
928
- const absolutePath = path14.resolve(clientDir, sanitizedPath.substring(1));
929
- if (!absolutePath.startsWith(clientDir)) {
930
- res.writeHead(403, { "Content-Type": "text/plain" });
931
- res.end("Forbidden");
932
- return;
933
- }
934
- try {
935
- if (await fs15.pathExists(absolutePath)) {
936
- const stat5 = await fs15.stat(absolutePath);
937
- let filePath = absolutePath;
938
- if (stat5.isDirectory()) {
939
- filePath = path14.join(absolutePath, "index.html");
940
- }
941
- const content = await fs15.readFile(filePath);
942
- const mimeType = mime.getType(filePath) || "application/octet-stream";
943
- res.writeHead(200, { "Content-Type": mimeType });
944
- res.end(content);
945
- } else {
946
- res.writeHead(404);
947
- 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;
948
943
  }
949
- } catch (error) {
950
- console.error("Error serving file:", error);
951
- res.writeHead(500);
952
- res.end("Internal Server Error");
953
944
  }
945
+ return result;
954
946
  }
955
- handleWebSocketConnection(ws) {
956
- this.clients.add(ws);
957
- console.log(`\uD83D\uDCE1 Web client connected (${this.clients.size} total)`);
958
- this.checkAndSendUpdateNotification(ws);
959
- ws.on("message", async (data) => {
960
- try {
961
- const message = JSON.parse(data.toString());
962
- if (message.type === "prompt") {
963
- await this.handlePrompt(message.content, ws);
964
- } else if (message.type === "get_file_tree") {
965
- await this.handleGetFileTree(ws);
966
- } else if (message.type === "get_file_content") {
967
- await this.handleGetFileContent(message.path, ws);
968
- } else if (message.type === "list_sessions") {
969
- await this.handleListSessions(ws);
970
- } else if (message.type === "switch_session") {
971
- await this.handleSwitchSession(message.sessionId, ws);
972
- }
973
- } catch (error) {
974
- console.error("WebSocket message error:", error);
975
- ws.send(JSON.stringify({ type: "error", content: "Invalid message format" }));
976
- }
977
- });
978
- ws.on("close", () => {
979
- this.clients.delete(ws);
980
- console.log(`\uD83D\uDCE1 Web client disconnected (${this.clients.size} remaining)`);
981
- });
982
- ws.on("error", (error) => {
983
- console.error("WebSocket error:", error);
984
- });
947
+ confirmOperation(confirmed, dontAskAgain) {
948
+ if (this.resolveConfirmation) {
949
+ this.resolveConfirmation({ confirmed, dontAskAgain });
950
+ this.resolveConfirmation = null;
951
+ this.pendingConfirmation = null;
952
+ }
985
953
  }
986
- async handlePrompt(prompt, ws) {
987
- try {
988
- ws.send(JSON.stringify({ type: "user_message", content: prompt }));
989
- const entries = await this.agent.processUserMessage(prompt);
990
- for (const entry of entries) {
991
- if (entry.type === "assistant") {
992
- ws.send(JSON.stringify({
993
- type: "assistant_message",
994
- content: entry.content
995
- }));
996
- } else if (entry.type === "tool_call") {
997
- ws.send(JSON.stringify({
998
- type: "tool_call",
999
- tool: entry.toolCall?.function.name,
1000
- content: "Executing..."
1001
- }));
1002
- } else if (entry.type === "tool_result") {
1003
- ws.send(JSON.stringify({
1004
- type: "tool_result",
1005
- tool: entry.toolCall?.function.name,
1006
- content: entry.content
1007
- }));
1008
- }
1009
- }
1010
- ws.send(JSON.stringify({ type: "done" }));
1011
- } catch (error) {
1012
- ws.send(JSON.stringify({
1013
- type: "error",
1014
- content: error.message
1015
- }));
954
+ rejectOperation(feedback) {
955
+ if (this.resolveConfirmation) {
956
+ this.resolveConfirmation({ confirmed: false, feedback });
957
+ this.resolveConfirmation = null;
958
+ this.pendingConfirmation = null;
1016
959
  }
1017
960
  }
1018
- async handleGetFileTree(ws) {
1019
- try {
1020
- const { getFileIndexer: getFileIndexer2 } = await Promise.resolve().then(() => (init_indexer(), exports_indexer));
1021
- const indexer = getFileIndexer2();
1022
- const index = indexer.getIndex();
1023
- if (!index) {
1024
- 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}"`);
1025
967
  return;
968
+ } catch (error) {
969
+ continue;
1026
970
  }
1027
- const tree = index.entries.filter((e) => !e.path.includes("node_modules") && !e.path.startsWith(".")).map((e) => ({
1028
- path: e.path,
1029
- name: path14.basename(e.path),
1030
- isDirectory: e.isDirectory,
1031
- size: e.size
1032
- })).slice(0, 500);
1033
- ws.send(JSON.stringify({ type: "file_tree", tree }));
1034
- } catch (error) {
1035
- ws.send(JSON.stringify({ type: "error", content: error.message }));
1036
971
  }
972
+ throw new Error("VS Code not found");
1037
973
  }
1038
- async handleGetFileContent(filePath, ws) {
1039
- try {
1040
- const fullPath = path14.join(process.cwd(), filePath);
1041
- if (!fullPath.startsWith(process.cwd())) {
1042
- throw new Error("Access denied");
1043
- }
1044
- const content = await fs15.readFile(fullPath, "utf-8");
1045
- ws.send(JSON.stringify({
1046
- type: "file_content",
1047
- path: filePath,
1048
- content: content.slice(0, 1e4)
1049
- }));
1050
- } catch (error) {
1051
- ws.send(JSON.stringify({ type: "error", content: error.message }));
1052
- }
974
+ isPending() {
975
+ return this.pendingConfirmation !== null;
1053
976
  }
1054
- async handleListSessions(ws) {
1055
- try {
1056
- const { getSessionManager: getSessionManager2 } = await Promise.resolve().then(() => (init_session_manager(), exports_session_manager));
1057
- const sessionManager = getSessionManager2();
1058
- const sessions = await sessionManager.listSessions();
1059
- ws.send(JSON.stringify({
1060
- type: "sessions_list",
1061
- sessions: sessions.map((s) => ({
1062
- id: s.id,
1063
- name: s.name,
1064
- workingDirectory: s.workingDirectory,
1065
- messageCount: s.messages.length,
1066
- lastAccessed: s.lastAccessed
1067
- }))
1068
- }));
1069
- } catch (error) {
1070
- ws.send(JSON.stringify({ type: "error", content: error.message }));
1071
- }
977
+ resetSession() {
978
+ this.sessionFlags = {
979
+ fileOperations: false,
980
+ bashCommands: false,
981
+ allOperations: false
982
+ };
1072
983
  }
1073
- async handleSwitchSession(sessionId, ws) {
1074
- try {
1075
- const { getSessionManager: getSessionManager2 } = await Promise.resolve().then(() => (init_session_manager(), exports_session_manager));
1076
- const sessionManager = getSessionManager2();
1077
- const session = await sessionManager.switchSession(sessionId);
1078
- if (session) {
1079
- ws.send(JSON.stringify({
1080
- type: "session_switched",
1081
- session: {
1082
- id: session.id,
1083
- name: session.name,
1084
- workingDirectory: session.workingDirectory,
1085
- messages: session.messages
1086
- }
1087
- }));
1088
- } else {
1089
- throw new Error("Session not found");
1090
- }
1091
- } catch (error) {
1092
- ws.send(JSON.stringify({ type: "error", content: error.message }));
1093
- }
1094
- }
1095
- async checkAndSendUpdateNotification(ws) {
1096
- try {
1097
- const pkg = await Promise.resolve().then(() => __toESM(require_package(), 1));
1098
- const { getUpdateChecker: getUpdateChecker2 } = await Promise.resolve().then(() => (init_update_checker(), exports_update_checker));
1099
- const updateChecker = getUpdateChecker2(pkg.version);
1100
- const updateInfo = await updateChecker.checkForUpdates();
1101
- if (updateInfo?.updateAvailable) {
1102
- ws.send(JSON.stringify({
1103
- type: "update_available",
1104
- currentVersion: updateInfo.currentVersion,
1105
- latestVersion: updateInfo.latestVersion
1106
- }));
1107
- }
1108
- } catch (error) {}
1109
- }
1110
- async start() {
1111
- return new Promise((resolve5, reject) => {
1112
- this.httpServer.listen(this.port, this.hostname, () => {
1113
- const url = `http://${this.hostname}:${this.port}`;
1114
- console.log(`\uD83C\uDF10 Web interface available at ${url}`);
1115
- resolve5();
1116
- });
1117
- this.httpServer.on("error", (error) => {
1118
- reject(error);
1119
- });
1120
- });
1121
- }
1122
- async openBrowser() {
1123
- const url = `http://${this.hostname}:${this.port}`;
1124
- try {
1125
- await open(url);
1126
- console.log(`\uD83D\uDE80 Opened browser at ${url}`);
1127
- } catch (error) {
1128
- console.warn(`Could not open browser automatically. Please visit ${url}`);
1129
- }
1130
- }
1131
- stop() {
1132
- this.clients.forEach((client) => {
1133
- client.close();
1134
- });
1135
- this.wss.close();
1136
- this.httpServer.close();
1137
- console.log("\uD83D\uDED1 Web server stopped");
1138
- }
1139
- }
1140
- var __dirname = "/home/runner/work/super-agent-cli/super-agent-cli/src/web";
1141
- var init_server = () => {};
1142
-
1143
- // src/utils/confirmation-service.ts
1144
- import { EventEmitter } from "events";
1145
- import { exec } from "child_process";
1146
- import { promisify } from "util";
1147
- var execAsync = promisify(exec);
1148
-
1149
- class ConfirmationService extends EventEmitter {
1150
- static instance;
1151
- skipConfirmationThisSession = false;
1152
- pendingConfirmation = null;
1153
- resolveConfirmation = null;
1154
- sessionFlags = {
1155
- fileOperations: false,
1156
- bashCommands: false,
1157
- allOperations: false
1158
- };
1159
- static getInstance() {
1160
- if (!ConfirmationService.instance) {
1161
- ConfirmationService.instance = new ConfirmationService;
1162
- }
1163
- return ConfirmationService.instance;
1164
- }
1165
- constructor() {
1166
- super();
1167
- }
1168
- async requestConfirmation(options, operationType = "file") {
1169
- if (this.sessionFlags.allOperations || operationType === "file" && this.sessionFlags.fileOperations || operationType === "bash" && this.sessionFlags.bashCommands) {
1170
- return { confirmed: true };
1171
- }
1172
- if (options.showVSCodeOpen) {
1173
- try {
1174
- await this.openInVSCode(options.filename);
1175
- } catch (error) {
1176
- options.showVSCodeOpen = false;
1177
- }
1178
- }
1179
- this.pendingConfirmation = new Promise((resolve) => {
1180
- this.resolveConfirmation = resolve;
1181
- });
1182
- setImmediate(() => {
1183
- this.emit("confirmation-requested", options);
1184
- });
1185
- const result = await this.pendingConfirmation;
1186
- if (result.dontAskAgain) {
1187
- if (operationType === "file") {
1188
- this.sessionFlags.fileOperations = true;
1189
- } else if (operationType === "bash") {
1190
- this.sessionFlags.bashCommands = true;
1191
- }
1192
- }
1193
- return result;
1194
- }
1195
- confirmOperation(confirmed, dontAskAgain) {
1196
- if (this.resolveConfirmation) {
1197
- this.resolveConfirmation({ confirmed, dontAskAgain });
1198
- this.resolveConfirmation = null;
1199
- this.pendingConfirmation = null;
1200
- }
1201
- }
1202
- rejectOperation(feedback) {
1203
- if (this.resolveConfirmation) {
1204
- this.resolveConfirmation({ confirmed: false, feedback });
1205
- this.resolveConfirmation = null;
1206
- this.pendingConfirmation = null;
1207
- }
1208
- }
1209
- async openInVSCode(filename) {
1210
- const commands = ["code", "code-insiders", "codium"];
1211
- for (const cmd of commands) {
1212
- try {
1213
- await execAsync(`which ${cmd}`);
1214
- await execAsync(`${cmd} "${filename}"`);
1215
- return;
1216
- } catch (error) {
1217
- continue;
1218
- }
1219
- }
1220
- throw new Error("VS Code not found");
1221
- }
1222
- isPending() {
1223
- return this.pendingConfirmation !== null;
1224
- }
1225
- resetSession() {
1226
- this.sessionFlags = {
1227
- fileOperations: false,
1228
- bashCommands: false,
1229
- allOperations: false
1230
- };
1231
- }
1232
- getSessionFlags() {
1233
- return { ...this.sessionFlags };
984
+ getSessionFlags() {
985
+ return { ...this.sessionFlags };
1234
986
  }
1235
987
  setSessionFlag(flagType, value) {
1236
988
  this.sessionFlags[flagType] = value;
@@ -8416,45 +8168,844 @@ function ChatInterface({
8416
8168
  onApiKeySet: handleApiKeySet
8417
8169
  }, undefined, false, undefined, this);
8418
8170
  }
8419
- return /* @__PURE__ */ jsxDEV16(ChatInterfaceWithAgent, {
8420
- agent: currentAgent,
8421
- initialMessage
8422
- }, 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;
8423
8974
  }
8424
8975
 
8425
8976
  // src/commands/mcp.ts
8426
8977
  init_config();
8427
- import { Command } from "commander";
8428
- import chalk from "chalk";
8978
+ import { Command as Command6 } from "commander";
8979
+ import chalk5 from "chalk";
8429
8980
  function createMCPCommand() {
8430
- const mcpCommand = new Command("mcp");
8981
+ const mcpCommand = new Command6("mcp");
8431
8982
  mcpCommand.description("Manage MCP (Model Context Protocol) servers");
8432
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) => {
8433
8984
  try {
8434
8985
  if (PREDEFINED_SERVERS[name]) {
8435
8986
  const config2 = PREDEFINED_SERVERS[name];
8436
8987
  addMCPServer(config2);
8437
- console.log(chalk.green(`✓ Added predefined MCP server: ${name}`));
8988
+ console.log(chalk5.green(`✓ Added predefined MCP server: ${name}`));
8438
8989
  const manager2 = getMCPManager();
8439
8990
  await manager2.addServer(config2);
8440
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
8991
+ console.log(chalk5.green(`✓ Connected to MCP server: ${name}`));
8441
8992
  const tools2 = manager2.getTools().filter((t) => t.serverName === name);
8442
- console.log(chalk.blue(` Available tools: ${tools2.length}`));
8993
+ console.log(chalk5.blue(` Available tools: ${tools2.length}`));
8443
8994
  return;
8444
8995
  }
8445
8996
  const transportType = options.transport.toLowerCase();
8446
8997
  if (transportType === "stdio") {
8447
8998
  if (!options.command) {
8448
- console.error(chalk.red("Error: --command is required for stdio transport"));
8999
+ console.error(chalk5.red("Error: --command is required for stdio transport"));
8449
9000
  process.exit(1);
8450
9001
  }
8451
9002
  } else if (transportType === "http" || transportType === "sse" || transportType === "streamable_http") {
8452
9003
  if (!options.url) {
8453
- console.error(chalk.red(`Error: --url is required for ${transportType} transport`));
9004
+ console.error(chalk5.red(`Error: --url is required for ${transportType} transport`));
8454
9005
  process.exit(1);
8455
9006
  }
8456
9007
  } else {
8457
- 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"));
8458
9009
  process.exit(1);
8459
9010
  }
8460
9011
  const env = {};
@@ -8483,14 +9034,14 @@ function createMCPCommand() {
8483
9034
  }
8484
9035
  };
8485
9036
  addMCPServer(config);
8486
- console.log(chalk.green(`✓ Added MCP server: ${name}`));
9037
+ console.log(chalk5.green(`✓ Added MCP server: ${name}`));
8487
9038
  const manager = getMCPManager();
8488
9039
  await manager.addServer(config);
8489
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
9040
+ console.log(chalk5.green(`✓ Connected to MCP server: ${name}`));
8490
9041
  const tools = manager.getTools().filter((t) => t.serverName === name);
8491
- console.log(chalk.blue(` Available tools: ${tools.length}`));
9042
+ console.log(chalk5.blue(` Available tools: ${tools.length}`));
8492
9043
  } catch (error) {
8493
- console.error(chalk.red(`Error adding MCP server: ${error.message}`));
9044
+ console.error(chalk5.red(`Error adding MCP server: ${error.message}`));
8494
9045
  process.exit(1);
8495
9046
  }
8496
9047
  });
@@ -8500,7 +9051,7 @@ function createMCPCommand() {
8500
9051
  try {
8501
9052
  config = JSON.parse(jsonConfig);
8502
9053
  } catch (error) {
8503
- console.error(chalk.red("Error: Invalid JSON configuration"));
9054
+ console.error(chalk5.red("Error: Invalid JSON configuration"));
8504
9055
  process.exit(1);
8505
9056
  }
8506
9057
  const serverConfig = {
@@ -8525,14 +9076,14 @@ function createMCPCommand() {
8525
9076
  }
8526
9077
  }
8527
9078
  addMCPServer(serverConfig);
8528
- console.log(chalk.green(`✓ Added MCP server: ${name}`));
9079
+ console.log(chalk5.green(`✓ Added MCP server: ${name}`));
8529
9080
  const manager = getMCPManager();
8530
9081
  await manager.addServer(serverConfig);
8531
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
9082
+ console.log(chalk5.green(`✓ Connected to MCP server: ${name}`));
8532
9083
  const tools = manager.getTools().filter((t) => t.serverName === name);
8533
- console.log(chalk.blue(` Available tools: ${tools.length}`));
9084
+ console.log(chalk5.blue(` Available tools: ${tools.length}`));
8534
9085
  } catch (error) {
8535
- console.error(chalk.red(`Error adding MCP server: ${error.message}`));
9086
+ console.error(chalk5.red(`Error adding MCP server: ${error.message}`));
8536
9087
  process.exit(1);
8537
9088
  }
8538
9089
  });
@@ -8541,9 +9092,9 @@ function createMCPCommand() {
8541
9092
  const manager = getMCPManager();
8542
9093
  await manager.removeServer(name);
8543
9094
  removeMCPServer(name);
8544
- console.log(chalk.green(`✓ Removed MCP server: ${name}`));
9095
+ console.log(chalk5.green(`✓ Removed MCP server: ${name}`));
8545
9096
  } catch (error) {
8546
- console.error(chalk.red(`Error removing MCP server: ${error.message}`));
9097
+ console.error(chalk5.red(`Error removing MCP server: ${error.message}`));
8547
9098
  process.exit(1);
8548
9099
  }
8549
9100
  });
@@ -8551,15 +9102,15 @@ function createMCPCommand() {
8551
9102
  const config = loadMCPConfig();
8552
9103
  const manager = getMCPManager();
8553
9104
  if (config.servers.length === 0) {
8554
- console.log(chalk.yellow("No MCP servers configured"));
9105
+ console.log(chalk5.yellow("No MCP servers configured"));
8555
9106
  return;
8556
9107
  }
8557
- console.log(chalk.bold("Configured MCP servers:"));
9108
+ console.log(chalk5.bold("Configured MCP servers:"));
8558
9109
  console.log();
8559
9110
  for (const server of config.servers) {
8560
9111
  const isConnected = manager.getServers().includes(server.name);
8561
- const status = isConnected ? chalk.green("✓ Connected") : chalk.red("✗ Disconnected");
8562
- 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}`);
8563
9114
  if (server.transport) {
8564
9115
  console.log(` Transport: ${server.transport.type}`);
8565
9116
  if (server.transport.type === "stdio") {
@@ -8592,15 +9143,15 @@ function createMCPCommand() {
8592
9143
  const config = loadMCPConfig();
8593
9144
  const serverConfig = config.servers.find((s) => s.name === name);
8594
9145
  if (!serverConfig) {
8595
- console.error(chalk.red(`Server ${name} not found`));
9146
+ console.error(chalk5.red(`Server ${name} not found`));
8596
9147
  process.exit(1);
8597
9148
  }
8598
- console.log(chalk.blue(`Testing connection to ${name}...`));
9149
+ console.log(chalk5.blue(`Testing connection to ${name}...`));
8599
9150
  const manager = getMCPManager();
8600
9151
  await manager.addServer(serverConfig);
8601
9152
  const tools = manager.getTools().filter((t) => t.serverName === name);
8602
- console.log(chalk.green(`✓ Successfully connected to ${name}`));
8603
- 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}`));
8604
9155
  if (tools.length > 0) {
8605
9156
  console.log(" Tools:");
8606
9157
  tools.forEach((tool) => {
@@ -8609,82 +9160,44 @@ function createMCPCommand() {
8609
9160
  });
8610
9161
  }
8611
9162
  } catch (error) {
8612
- console.error(chalk.red(`✗ Failed to connect to ${name}: ${error.message}`));
9163
+ console.error(chalk5.red(`✗ Failed to connect to ${name}: ${error.message}`));
8613
9164
  process.exit(1);
8614
9165
  }
8615
9166
  });
8616
9167
  return mcpCommand;
8617
9168
  }
8618
9169
 
8619
- // src/index.ts
8620
- var import__package = __toESM(require_package(), 1);
8621
- import { program } from "commander";
8622
- import * as dotenv from "dotenv";
8623
- import { render } from "ink";
8624
- import React4 from "react";
8625
- dotenv.config();
8626
- process.on("SIGTERM", () => {
8627
- if (process.stdin.isTTY && process.stdin.setRawMode) {
8628
- try {
8629
- process.stdin.setRawMode(false);
8630
- } catch (e) {}
8631
- }
8632
- console.log(`
8633
- Gracefully shutting down...`);
8634
- process.exit(0);
8635
- });
8636
- process.on("uncaughtException", (error) => {
8637
- console.error("Uncaught exception:", error);
8638
- process.exit(1);
8639
- });
8640
- process.on("unhandledRejection", (reason, promise) => {
8641
- console.error("Unhandled rejection at:", promise, "reason:", reason);
8642
- process.exit(1);
8643
- });
8644
- function ensureUserSettingsDirectory() {
8645
- try {
8646
- const manager = getSettingsManager();
8647
- manager.loadUserSettings();
8648
- } catch (error) {}
8649
- }
8650
- function loadApiKey() {
9170
+ // src/commands/git.ts
9171
+ init_settings_manager();
9172
+ import { Command as Command7 } from "commander";
9173
+ async function loadApiKey() {
8651
9174
  const manager = getSettingsManager();
8652
9175
  return manager.getApiKey();
8653
9176
  }
8654
- function loadBaseURL() {
9177
+ async function loadBaseURL() {
8655
9178
  const manager = getSettingsManager();
8656
9179
  return manager.getBaseURL();
8657
9180
  }
9181
+ async function loadModel() {
9182
+ const manager = getSettingsManager();
9183
+ return process.env.SUPER_AGENT_MODEL || manager.getCurrentModel();
9184
+ }
8658
9185
  async function saveCommandLineSettings(apiKey, baseURL) {
8659
- try {
8660
- const manager = getSettingsManager();
8661
- const settings = manager.loadUserSettings();
8662
- const activeProviderId = settings.active_provider;
8663
- if (!settings.providers[activeProviderId]) {
8664
- return;
8665
- }
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]) {
8666
9193
  if (apiKey) {
8667
9194
  settings.providers[activeProviderId].api_key = apiKey;
8668
- console.log(`✅ API key saved for provider '${activeProviderId}' to ~/.super-agent/settings.json`);
8669
9195
  }
8670
9196
  if (baseURL) {
8671
9197
  settings.providers[activeProviderId].base_url = baseURL;
8672
- console.log(`✅ Base URL saved for provider '${activeProviderId}' to ~/.super-agent/settings.json`);
8673
9198
  }
8674
9199
  manager.saveUserSettings(settings);
8675
- } catch (error) {
8676
- console.warn("⚠️ Could not save settings to file:", error instanceof Error ? error.message : "Unknown error");
8677
- }
8678
- }
8679
- function loadModel() {
8680
- let model = process.env.SUPER_AGENT_MODEL;
8681
- if (!model) {
8682
- try {
8683
- const manager = getSettingsManager();
8684
- model = manager.getCurrentModel();
8685
- } catch (error) {}
8686
9200
  }
8687
- return model;
8688
9201
  }
8689
9202
  async function handleCommitAndPushHeadless(apiKey, baseURL, model, maxToolRounds) {
8690
9203
  try {
@@ -8759,6 +9272,120 @@ Respond with ONLY the commit message, no additional text.`;
8759
9272
  process.exit(1);
8760
9273
  }
8761
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
+ }
8762
9389
  async function processPromptHeadless(prompt, apiKey, baseURL, model, maxToolRounds) {
8763
9390
  try {
8764
9391
  const agent = new SuperAgent(apiKey, baseURL, model, maxToolRounds);
@@ -8823,9 +9450,9 @@ program.name("super-agent").description("A conversational AI CLI tool powered by
8823
9450
  }
8824
9451
  }
8825
9452
  try {
8826
- const apiKey = options.apiKey || loadApiKey();
8827
- const baseURL = options.baseUrl || loadBaseURL();
8828
- const model = options.model || loadModel();
9453
+ const apiKey = options.apiKey || loadApiKey2();
9454
+ const baseURL = options.baseUrl || loadBaseURL2();
9455
+ const model = options.model || loadModel2();
8829
9456
  const maxToolRounds = parseInt(options.maxToolRounds) || 400;
8830
9457
  if (!apiKey && !options.prompt) {
8831
9458
  console.warn("⚠️ Warning: No API key found. Some features may not work. Use /config or set SUPER_AGENT_API_KEY.");
@@ -8834,7 +9461,7 @@ program.name("super-agent").description("A conversational AI CLI tool powered by
8834
9461
  process.exit(1);
8835
9462
  }
8836
9463
  if (options.apiKey || options.baseUrl) {
8837
- await saveCommandLineSettings(options.apiKey, options.baseUrl);
9464
+ await saveCommandLineSettings2(options.apiKey, options.baseUrl);
8838
9465
  }
8839
9466
  if (options.prompt) {
8840
9467
  await processPromptHeadless(options.prompt, apiKey, baseURL, model, maxToolRounds);
@@ -8862,141 +9489,6 @@ program.name("super-agent").description("A conversational AI CLI tool powered by
8862
9489
  process.exit(1);
8863
9490
  }
8864
9491
  });
8865
- var aboutCommand = program.command("about").description("Show information about the Super Agent CLI").action(() => {
8866
- console.log(import__package.default.name + " " + import__package.default.version);
8867
- console.log(import__package.default.description);
8868
- console.log(`
8869
- Maintained by: ` + import__package.default.author);
8870
- console.log(`
8871
- Source code: ` + import__package.default.repository.url);
8872
- console.log(`
8873
- Funding: ` + import__package.default.funding);
8874
- process.exit(0);
8875
- });
8876
- var pluginsCommand = program.command("plugins list/install/uninstall <name> / <path>").description("Manage plugins for Super Agent CLI");
8877
- pluginsCommand.command("list").description("List installed plugins").action(() => {
8878
- console.log("List installed plugins");
8879
- process.exit(0);
8880
- });
8881
- pluginsCommand.command("install <name> / <path>").description("Install a plugin").action(() => {
8882
- console.log("Install a plugin");
8883
- process.exit(0);
8884
- });
8885
- pluginsCommand.command("uninstall <name>").description("Uninstall a plugin").action(() => {
8886
- console.log("Uninstall a plugin");
8887
- process.exit(0);
8888
- });
8889
- var gitCommand = program.command("git").description("Git operations with AI assistance");
8890
- 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) => {
8891
- if (options.directory) {
8892
- try {
8893
- process.chdir(options.directory);
8894
- } catch (error) {
8895
- console.error(`Error changing directory to ${options.directory}:`, error.message);
8896
- process.exit(1);
8897
- }
8898
- }
8899
- try {
8900
- const apiKey = options.apiKey || loadApiKey();
8901
- const baseURL = options.baseUrl || loadBaseURL();
8902
- const model = options.model || loadModel();
8903
- const maxToolRounds = parseInt(options.maxToolRounds) || 400;
8904
- if (!apiKey) {
8905
- console.error("❌ Error: API key required for git operations. Set SUPER_AGENT_API_KEY environment variable.");
8906
- process.exit(1);
8907
- }
8908
- if (options.apiKey || options.baseUrl) {
8909
- await saveCommandLineSettings(options.apiKey, options.baseUrl);
8910
- }
8911
- await handleCommitAndPushHeadless(apiKey, baseURL, model, maxToolRounds);
8912
- } catch (error) {
8913
- console.error("❌ Error during git commit-and-push:", error.message);
8914
- process.exit(1);
8915
- }
8916
- });
8917
- 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) => {
8918
- if (options.directory) {
8919
- try {
8920
- process.chdir(options.directory);
8921
- } catch (error) {
8922
- console.error(`Error changing directory to ${options.directory}:`, error.message);
8923
- process.exit(1);
8924
- }
8925
- }
8926
- try {
8927
- const { WebServer: WebServer2 } = await Promise.resolve().then(() => (init_server(), exports_server));
8928
- const apiKey = options.apiKey || loadApiKey();
8929
- const baseURL = options.baseUrl || loadBaseURL();
8930
- const model = options.model || loadModel();
8931
- const maxToolRounds = parseInt(options.maxToolRounds) || 400;
8932
- if (!apiKey) {
8933
- console.warn("⚠️ Warning: No API key found. Web interface may not work properly.");
8934
- }
8935
- if (options.apiKey || options.baseUrl) {
8936
- await saveCommandLineSettings(options.apiKey, options.baseUrl);
8937
- }
8938
- const agent = new SuperAgent(apiKey || "", baseURL, model, maxToolRounds);
8939
- const server = new WebServer2({
8940
- hostname: options.hostname,
8941
- port: parseInt(options.port),
8942
- agent
8943
- });
8944
- await server.start();
8945
- if (options.open !== false) {
8946
- await server.openBrowser();
8947
- }
8948
- process.on("SIGINT", () => {
8949
- server.stop();
8950
- process.exit(0);
8951
- });
8952
- } catch (error) {
8953
- console.error("❌ Error starting web server:", error.message);
8954
- process.exit(1);
8955
- }
8956
- });
8957
- 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) => {
8958
- if (options.directory) {
8959
- try {
8960
- process.chdir(options.directory);
8961
- } catch (error) {
8962
- console.error(`Error changing directory to ${options.directory}:`, error.message);
8963
- process.exit(1);
8964
- }
8965
- }
8966
- try {
8967
- const { WebServer: WebServer2 } = await Promise.resolve().then(() => (init_server(), exports_server));
8968
- const apiKey = options.apiKey || loadApiKey();
8969
- const baseURL = options.baseUrl || loadBaseURL();
8970
- const model = options.model || loadModel();
8971
- const maxToolRounds = parseInt(options.maxToolRounds) || 400;
8972
- if (!apiKey) {
8973
- console.warn("⚠️ Warning: No API key found. Some features may not work.");
8974
- }
8975
- if (options.apiKey || options.baseUrl) {
8976
- await saveCommandLineSettings(options.apiKey, options.baseUrl);
8977
- }
8978
- const agent = new SuperAgent(apiKey || "", baseURL, model, maxToolRounds);
8979
- const server = new WebServer2({
8980
- hostname: options.hostname,
8981
- port: parseInt(options.port),
8982
- agent
8983
- });
8984
- await server.start();
8985
- if (options.open !== false) {
8986
- await server.openBrowser();
8987
- }
8988
- console.log(`\uD83E\uDD16 Starting CLI interface...
8989
- `);
8990
- ensureUserSettingsDirectory();
8991
- render(React4.createElement(ChatInterface, { agent }));
8992
- process.on("SIGINT", () => {
8993
- server.stop();
8994
- process.exit(0);
8995
- });
8996
- } catch (error) {
8997
- console.error("❌ Error starting serve mode:", error.message);
8998
- process.exit(1);
8999
- }
9000
- });
9001
- program.addCommand(createMCPCommand());
9492
+ registerCommands(program);
9493
+ program.parse();
9002
9494
  program.parse();