@involvex/super-agent-cli 0.0.61 → 0.0.63

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
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
2
3
  var __create = Object.create;
3
4
  var __getProtoOf = Object.getPrototypeOf;
4
5
  var __defProp = Object.defineProperty;
@@ -41,12 +42,14 @@ var __export = (target, all) => {
41
42
  });
42
43
  };
43
44
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
45
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
44
46
 
45
47
  // src/utils/settings-manager.ts
46
48
  var exports_settings_manager = {};
47
49
  __export(exports_settings_manager, {
48
50
  getSettingsManager: () => getSettingsManager,
49
- SettingsManager: () => SettingsManager
51
+ SettingsManager: () => SettingsManager,
52
+ PROVIDER_MODELS: () => PROVIDER_MODELS
50
53
  });
51
54
  import * as path from "path";
52
55
  import * as os from "os";
@@ -87,7 +90,20 @@ class SettingsManager {
87
90
  }
88
91
  const content = fs.readFileSync(this.userSettingsPath, "utf-8");
89
92
  const settings = JSON.parse(content);
90
- return { ...DEFAULT_USER_SETTINGS, ...settings };
93
+ const mergedProviders = { ...DEFAULT_USER_SETTINGS.providers };
94
+ if (settings.providers) {
95
+ for (const [key, value] of Object.entries(settings.providers)) {
96
+ mergedProviders[key] = {
97
+ ...mergedProviders[key] || {},
98
+ ...value
99
+ };
100
+ }
101
+ }
102
+ return {
103
+ ...DEFAULT_USER_SETTINGS,
104
+ ...settings,
105
+ providers: mergedProviders
106
+ };
91
107
  } catch (error) {
92
108
  console.warn("Failed to load user settings:", error);
93
109
  return { ...DEFAULT_USER_SETTINGS };
@@ -175,6 +191,12 @@ class SettingsManager {
175
191
  if (models) {
176
192
  return models;
177
193
  }
194
+ if (activeProvider) {
195
+ const config = this.getEffectiveSettings().providers[activeProvider];
196
+ if (config && config.model) {
197
+ return [config.model];
198
+ }
199
+ }
178
200
  return [
179
201
  "grok-beta",
180
202
  "grok-vision-beta",
@@ -336,6 +358,94 @@ var init_settings_manager = __esm(() => {
336
358
  DEFAULT_PROJECT_SETTINGS = {};
337
359
  });
338
360
 
361
+ // src/utils/file-utils.ts
362
+ var exports_file_utils = {};
363
+ __export(exports_file_utils, {
364
+ resolveSourcePath: () => resolveSourcePath,
365
+ listFilesRecursive: () => listFilesRecursive,
366
+ filterFileEntries: () => filterFileEntries,
367
+ expandHome: () => expandHome
368
+ });
369
+ import * as fs2 from "fs-extra";
370
+ import * as path2 from "path";
371
+ import * as os2 from "os";
372
+ function expandHome(filepath) {
373
+ if (filepath.startsWith("~")) {
374
+ return path2.join(os2.homedir(), filepath.slice(1));
375
+ }
376
+ return filepath;
377
+ }
378
+ function resolveSourcePath(source) {
379
+ const defaults = {
380
+ gemini: "~/.gemini",
381
+ claude: "~/.claude",
382
+ kilo: "~/.kilocode"
383
+ };
384
+ const rawPath = defaults[source.toLowerCase()] || source;
385
+ return expandHome(rawPath);
386
+ }
387
+ async function listFilesRecursive(dir, baseDir = dir, maxDepth = 3) {
388
+ const result = [];
389
+ try {
390
+ const entries = await fs2.readdir(dir, { withFileTypes: true });
391
+ for (const entry of entries) {
392
+ const fullPath = path2.join(dir, entry.name);
393
+ const relativePath = path2.relative(baseDir, fullPath);
394
+ const isIgnored = [
395
+ "node_modules",
396
+ ".git",
397
+ "dist",
398
+ "build",
399
+ ".next",
400
+ "target",
401
+ "vendor"
402
+ ].includes(entry.name);
403
+ if (isIgnored) {
404
+ continue;
405
+ }
406
+ if (entry.name.startsWith(".") && entry.name !== ".env") {
407
+ continue;
408
+ }
409
+ result.push({
410
+ name: entry.name,
411
+ path: relativePath,
412
+ isDirectory: entry.isDirectory()
413
+ });
414
+ if (entry.isDirectory() && maxDepth > 0) {
415
+ const subFiles = await listFilesRecursive(fullPath, baseDir, maxDepth - 1);
416
+ result.push(...subFiles);
417
+ }
418
+ }
419
+ } catch (error) {}
420
+ return result;
421
+ }
422
+ function filterFileEntries(entries, query) {
423
+ if (!query) {
424
+ return entries.slice(0, 20);
425
+ }
426
+ const lowerQuery = query.toLowerCase();
427
+ return entries.filter((e) => e.path.toLowerCase().includes(lowerQuery)).sort((a, b) => {
428
+ const aLower = a.name.toLowerCase();
429
+ const bLower = b.name.toLowerCase();
430
+ if (aLower === lowerQuery && bLower !== lowerQuery) {
431
+ return -1;
432
+ }
433
+ if (bLower === lowerQuery && aLower !== lowerQuery) {
434
+ return 1;
435
+ }
436
+ const aPathLower = a.path.toLowerCase();
437
+ const bPathLower = b.path.toLowerCase();
438
+ if (aPathLower.startsWith(lowerQuery) && !bPathLower.startsWith(lowerQuery)) {
439
+ return -1;
440
+ }
441
+ if (bPathLower.startsWith(lowerQuery) && !aPathLower.startsWith(lowerQuery)) {
442
+ return 1;
443
+ }
444
+ return a.path.length - b.path.length;
445
+ }).slice(0, 20);
446
+ }
447
+ var init_file_utils = () => {};
448
+
339
449
  // src/mcp/config.ts
340
450
  var exports_config = {};
341
451
  __export(exports_config, {
@@ -412,14 +522,231 @@ var init_config = __esm(() => {
412
522
  PREDEFINED_SERVERS = {};
413
523
  });
414
524
 
525
+ // src/agents/manager.ts
526
+ var exports_manager = {};
527
+ __export(exports_manager, {
528
+ AgentsManager: () => AgentsManager
529
+ });
530
+ import fs6 from "fs/promises";
531
+ import path6 from "path";
532
+
533
+ class AgentsManager {
534
+ static instance;
535
+ agentsPath;
536
+ constructor() {
537
+ this.agentsPath = path6.join(getSettingsManager().getStorageDirectory(), "agents");
538
+ }
539
+ static getInstance() {
540
+ if (!AgentsManager.instance) {
541
+ AgentsManager.instance = new AgentsManager;
542
+ }
543
+ return AgentsManager.instance;
544
+ }
545
+ async ensureAgentsDirectory() {
546
+ try {
547
+ await fs6.mkdir(this.agentsPath, { recursive: true });
548
+ } catch (error) {}
549
+ }
550
+ async listAgents() {
551
+ await this.ensureAgentsDirectory();
552
+ try {
553
+ const files = await fs6.readdir(this.agentsPath);
554
+ const agents = [];
555
+ for (const file of files) {
556
+ if (file.endsWith(".json")) {
557
+ try {
558
+ const content = await fs6.readFile(path6.join(this.agentsPath, file), "utf-8");
559
+ agents.push(JSON.parse(content));
560
+ } catch (e) {}
561
+ }
562
+ }
563
+ return agents;
564
+ } catch (error) {
565
+ return [];
566
+ }
567
+ }
568
+ async getAgent(name) {
569
+ try {
570
+ const content = await fs6.readFile(path6.join(this.agentsPath, `${name}.json`), "utf-8");
571
+ return JSON.parse(content);
572
+ } catch (error) {
573
+ return null;
574
+ }
575
+ }
576
+ async createAgent(config) {
577
+ await this.ensureAgentsDirectory();
578
+ const filePath = path6.join(this.agentsPath, `${config.name}.json`);
579
+ await fs6.writeFile(filePath, JSON.stringify(config, null, 2));
580
+ }
581
+ async generateAgent(name, description, agent) {
582
+ const prompt = `Create a configuration for an AI agent named "${name}" based on this description: "${description}".
583
+
584
+ The configuration should be a JSON object matching this interface:
585
+ interface AgentConfig {
586
+ name: string;
587
+ role: string;
588
+ description: string;
589
+ model?: string; // suggest a model if appropriate, or leave undefined
590
+ tools?: string[]; // suggest relevant tools/skills names
591
+ temperature?: number;
592
+ systemPrompt?: string; // a detailed system prompt for this agent
593
+ }
594
+
595
+ Return ONLY the JSON object.`;
596
+ const response = await agent.processUserMessage(prompt);
597
+ let jsonData = "";
598
+ for (const entry of response) {
599
+ if (entry.type === "assistant") {
600
+ const match = entry.content.match(/```(?:json)?\n([\s\S]*?)```/);
601
+ if (match) {
602
+ jsonData = match[1];
603
+ break;
604
+ } else {
605
+ if (entry.content.trim().startsWith("{")) {
606
+ jsonData = entry.content;
607
+ }
608
+ }
609
+ }
610
+ }
611
+ if (!jsonData) {
612
+ throw new Error("Failed to generate agent configuration");
613
+ }
614
+ try {
615
+ const config = JSON.parse(jsonData);
616
+ config.name = name;
617
+ await this.createAgent(config);
618
+ } catch (e) {
619
+ throw new Error(`Failed to parse generated agent config: ${e.message}`);
620
+ }
621
+ }
622
+ async deleteAgent(name) {
623
+ try {
624
+ const filePath = path6.join(this.agentsPath, `${name}.json`);
625
+ await fs6.unlink(filePath);
626
+ } catch (error) {
627
+ throw new Error(`Failed to delete agent '${name}'`);
628
+ }
629
+ }
630
+ }
631
+ var init_manager = __esm(() => {
632
+ init_settings_manager();
633
+ });
634
+
635
+ // src/skills/manager.ts
636
+ var exports_manager2 = {};
637
+ __export(exports_manager2, {
638
+ SkillsManager: () => SkillsManager
639
+ });
640
+ import fs7 from "fs/promises";
641
+ import path7 from "path";
642
+
643
+ class SkillsManager {
644
+ static instance;
645
+ skillsPath;
646
+ constructor() {
647
+ this.skillsPath = path7.join(getSettingsManager().getStorageDirectory(), "skills");
648
+ }
649
+ static getInstance() {
650
+ if (!SkillsManager.instance) {
651
+ SkillsManager.instance = new SkillsManager;
652
+ }
653
+ return SkillsManager.instance;
654
+ }
655
+ async ensureSkillsDirectory() {
656
+ try {
657
+ await fs7.mkdir(this.skillsPath, { recursive: true });
658
+ } catch (error) {}
659
+ }
660
+ async listSkills() {
661
+ await this.ensureSkillsDirectory();
662
+ try {
663
+ const files = await fs7.readdir(this.skillsPath);
664
+ return files.filter((file) => file.endsWith(".ts") || file.endsWith(".js") || file.endsWith(".json")).map((file) => path7.parse(file).name);
665
+ } catch (error) {
666
+ return [];
667
+ }
668
+ }
669
+ async getSkillPath(name) {
670
+ const extensions = [".ts", ".js", ".json"];
671
+ for (const ext of extensions) {
672
+ const fullPath = path7.join(this.skillsPath, `${name}${ext}`);
673
+ try {
674
+ await fs7.access(fullPath);
675
+ return fullPath;
676
+ } catch {
677
+ continue;
678
+ }
679
+ }
680
+ throw new Error(`Skill '${name}' not found`);
681
+ }
682
+ async getSkillContent(name) {
683
+ const skillPath = await this.getSkillPath(name);
684
+ return await fs7.readFile(skillPath, "utf-8");
685
+ }
686
+ async createSkill(name, description, agent) {
687
+ await this.ensureSkillsDirectory();
688
+ const prompt = `Create a robust TypeScript skill for the Super Agent CLI named "${name}".
689
+
690
+ Description: ${description}
691
+
692
+ The skill should be a module that exports a default function or class that implements the desired functionality.
693
+ It should valid standalone TypeScript code.
694
+ Include comments explaining how it works.
695
+
696
+ Structure:
697
+ \`\`\`typescript
698
+ // ${name} skill
699
+ export default async function(args: any) {
700
+ // implementation
701
+ }
702
+ \`\`\`
703
+
704
+ Return ONLY the code block.`;
705
+ const response = await agent.processUserMessage(prompt);
706
+ let code = "";
707
+ for (const entry of response) {
708
+ if (entry.type === "assistant") {
709
+ const match = entry.content.match(/```(?:typescript|ts)?\n([\s\S]*?)```/);
710
+ if (match) {
711
+ code = match[1];
712
+ break;
713
+ } else {
714
+ code = entry.content;
715
+ }
716
+ }
717
+ }
718
+ if (!code) {
719
+ throw new Error("Failed to generate skill code");
720
+ }
721
+ const filePath = path7.join(this.skillsPath, `${name}.ts`);
722
+ await fs7.writeFile(filePath, code);
723
+ }
724
+ async deleteSkill(name) {
725
+ try {
726
+ const skillPath = await this.getSkillPath(name);
727
+ await fs7.unlink(skillPath);
728
+ } catch (error) {
729
+ throw new Error(`Failed to delete skill '${name}': ${error.message}`);
730
+ }
731
+ }
732
+ async saveSkill(name, content) {
733
+ await this.ensureSkillsDirectory();
734
+ const filePath = path7.join(this.skillsPath, name.endsWith(".ts") ? name : `${name}.ts`);
735
+ await fs7.writeFile(filePath, content);
736
+ }
737
+ }
738
+ var init_manager2 = __esm(() => {
739
+ init_settings_manager();
740
+ });
741
+
415
742
  // src/indexing/indexer.ts
416
743
  var exports_indexer = {};
417
744
  __export(exports_indexer, {
418
745
  getFileIndexer: () => getFileIndexer,
419
746
  FileIndexer: () => FileIndexer
420
747
  });
421
- import * as fs9 from "fs-extra";
422
- import * as path8 from "path";
748
+ import * as fs11 from "fs-extra";
749
+ import * as path10 from "path";
423
750
 
424
751
  class FileIndexer {
425
752
  static instance;
@@ -429,7 +756,7 @@ class FileIndexer {
429
756
  isScanning = false;
430
757
  constructor() {
431
758
  const settingsManager = getSettingsManager();
432
- this.storagePath = path8.join(settingsManager.getStorageDirectory(), INDEX_FILENAME);
759
+ this.storagePath = path10.join(settingsManager.getStorageDirectory(), INDEX_FILENAME);
433
760
  this.rootPath = process.cwd();
434
761
  }
435
762
  static getInstance() {
@@ -440,8 +767,8 @@ class FileIndexer {
440
767
  }
441
768
  async loadIndex() {
442
769
  try {
443
- if (fs9.existsSync(this.storagePath)) {
444
- const content = await fs9.readFile(this.storagePath, "utf-8");
770
+ if (fs11.existsSync(this.storagePath)) {
771
+ const content = await fs11.readFile(this.storagePath, "utf-8");
445
772
  this.index = JSON.parse(content);
446
773
  if (!this.index || this.index.metadata.version !== INDEX_VERSION || this.index.metadata.rootPath !== this.rootPath) {
447
774
  this.index = null;
@@ -457,7 +784,7 @@ class FileIndexer {
457
784
  return;
458
785
  }
459
786
  try {
460
- await fs9.outputFile(this.storagePath, JSON.stringify(this.index, null, 2));
787
+ await fs11.outputFile(this.storagePath, JSON.stringify(this.index, null, 2));
461
788
  } catch (error) {
462
789
  console.error("Failed to save file index:", error);
463
790
  }
@@ -483,15 +810,15 @@ class FileIndexer {
483
810
  ];
484
811
  const entries = [];
485
812
  const scanDir = async (dir) => {
486
- const files = await fs9.readdir(dir, { withFileTypes: true });
813
+ const files = await fs11.readdir(dir, { withFileTypes: true });
487
814
  for (const file of files) {
488
815
  if (ignoreList.includes(file.name) || file.name.startsWith(".")) {
489
816
  if (file.name !== ".env") {
490
817
  continue;
491
818
  }
492
819
  }
493
- const fullPath = path8.join(dir, file.name);
494
- const relativePath = path8.relative(this.rootPath, fullPath);
820
+ const fullPath = path10.join(dir, file.name);
821
+ const relativePath = path10.relative(this.rootPath, fullPath);
495
822
  if (file.isDirectory()) {
496
823
  entries.push({
497
824
  path: relativePath,
@@ -501,7 +828,7 @@ class FileIndexer {
501
828
  });
502
829
  await scanDir(fullPath);
503
830
  } else {
504
- const stats = await fs9.stat(fullPath);
831
+ const stats = await fs11.stat(fullPath);
505
832
  entries.push({
506
833
  path: relativePath,
507
834
  size: stats.size,
@@ -536,16 +863,130 @@ var init_indexer = __esm(() => {
536
863
  init_settings_manager();
537
864
  });
538
865
 
866
+ // src/utils/session-manager.ts
867
+ var exports_session_manager = {};
868
+ __export(exports_session_manager, {
869
+ getSessionManager: () => getSessionManager,
870
+ SessionManager: () => SessionManager
871
+ });
872
+ import * as fs15 from "fs-extra";
873
+ import * as path14 from "path";
874
+
875
+ class SessionManager {
876
+ static instance;
877
+ sessionsDir;
878
+ currentSession = null;
879
+ constructor() {
880
+ const settingsManager = getSettingsManager();
881
+ this.sessionsDir = path14.join(settingsManager.getStorageDirectory(), "sessions");
882
+ fs15.ensureDirSync(this.sessionsDir);
883
+ }
884
+ static getInstance() {
885
+ if (!SessionManager.instance) {
886
+ SessionManager.instance = new SessionManager;
887
+ }
888
+ return SessionManager.instance;
889
+ }
890
+ generateSessionId(workingDir) {
891
+ const normalized = path14.normalize(workingDir).toLowerCase();
892
+ return Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
893
+ }
894
+ getSessionFilePath(sessionId) {
895
+ return path14.join(this.sessionsDir, `${sessionId}.json`);
896
+ }
897
+ async getOrCreateSession(workingDirectory, name) {
898
+ const sessionId = this.generateSessionId(workingDirectory);
899
+ const sessionFile = this.getSessionFilePath(sessionId);
900
+ try {
901
+ if (await fs15.pathExists(sessionFile)) {
902
+ const session = await fs15.readJson(sessionFile);
903
+ session.lastAccessed = Date.now();
904
+ this.currentSession = session;
905
+ await this.saveSession(session);
906
+ return session;
907
+ }
908
+ } catch (error) {}
909
+ const newSession = {
910
+ id: sessionId,
911
+ workingDirectory,
912
+ name: name || path14.basename(workingDirectory),
913
+ messages: [],
914
+ lastAccessed: Date.now(),
915
+ createdAt: Date.now()
916
+ };
917
+ this.currentSession = newSession;
918
+ await this.saveSession(newSession);
919
+ return newSession;
920
+ }
921
+ async saveSession(session) {
922
+ const sessionFile = this.getSessionFilePath(session.id);
923
+ await fs15.outputJson(sessionFile, session, { spaces: 2 });
924
+ }
925
+ async addMessage(message) {
926
+ if (!this.currentSession) {
927
+ throw new Error("No active session");
928
+ }
929
+ this.currentSession.messages.push(message);
930
+ this.currentSession.lastAccessed = Date.now();
931
+ await this.saveSession(this.currentSession);
932
+ }
933
+ async listSessions() {
934
+ const sessionFiles = await fs15.readdir(this.sessionsDir);
935
+ const sessions = [];
936
+ for (const file of sessionFiles) {
937
+ if (file.endsWith(".json")) {
938
+ try {
939
+ const session = await fs15.readJson(path14.join(this.sessionsDir, file));
940
+ sessions.push(session);
941
+ } catch (error) {}
942
+ }
943
+ }
944
+ sessions.sort((a, b) => b.lastAccessed - a.lastAccessed);
945
+ return sessions;
946
+ }
947
+ async deleteSession(sessionId) {
948
+ const sessionFile = this.getSessionFilePath(sessionId);
949
+ if (await fs15.pathExists(sessionFile)) {
950
+ await fs15.remove(sessionFile);
951
+ }
952
+ }
953
+ getCurrentSession() {
954
+ return this.currentSession;
955
+ }
956
+ async switchSession(sessionId) {
957
+ const sessionFile = this.getSessionFilePath(sessionId);
958
+ try {
959
+ if (await fs15.pathExists(sessionFile)) {
960
+ const session = await fs15.readJson(sessionFile);
961
+ session.lastAccessed = Date.now();
962
+ this.currentSession = session;
963
+ await this.saveSession(session);
964
+ return session;
965
+ }
966
+ } catch (error) {}
967
+ return null;
968
+ }
969
+ }
970
+ function getSessionManager() {
971
+ return SessionManager.getInstance();
972
+ }
973
+ var init_session_manager = __esm(() => {
974
+ init_settings_manager();
975
+ });
976
+
539
977
  // package.json
540
978
  var require_package = __commonJS((exports, module) => {
541
979
  module.exports = {
542
980
  name: "@involvex/super-agent-cli",
543
- version: "0.0.61",
981
+ version: "0.0.63",
544
982
  description: "An open-source AI agent that brings the power of Super Agent directly into your terminal.",
545
983
  keywords: [
546
984
  "cli",
547
985
  "agent",
548
- "text-editor",
986
+ "cli-agent",
987
+ "ai-cli",
988
+ "coding-cli",
989
+ "ai-coding-cli",
549
990
  "ai"
550
991
  ],
551
992
  homepage: "https://involvex.github.io/super-agent-cli/",
@@ -592,6 +1033,7 @@ var require_package = __commonJS((exports, module) => {
592
1033
  dependencies: {
593
1034
  "@google/generative-ai": "^0.24.1",
594
1035
  "@modelcontextprotocol/sdk": "^1.25.3",
1036
+ "@types/mime": "^4.0.0",
595
1037
  axios: "^1.13.4",
596
1038
  cfonts: "^3.3.1",
597
1039
  chalk: "^5.6.2",
@@ -600,7 +1042,9 @@ var require_package = __commonJS((exports, module) => {
600
1042
  dotenv: "^17.2.3",
601
1043
  enquirer: "^2.4.1",
602
1044
  "fs-extra": "^11.3.3",
1045
+ ignore: "^7.0.5",
603
1046
  ink: "^6.6.0",
1047
+ inquirer: "^13.2.2",
604
1048
  marked: "^17.0.1",
605
1049
  "marked-terminal": "^7.3.0",
606
1050
  mime: "^4.1.0",
@@ -638,46 +1082,14 @@ var require_package = __commonJS((exports, module) => {
638
1082
  };
639
1083
  });
640
1084
 
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
1085
  // src/utils/update-checker.ts
674
1086
  var exports_update_checker = {};
675
1087
  __export(exports_update_checker, {
676
1088
  getUpdateChecker: () => getUpdateChecker,
677
1089
  UpdateChecker: () => UpdateChecker
678
1090
  });
679
- import * as fs13 from "fs-extra";
680
- import * as path12 from "path";
1091
+ import * as fs16 from "fs-extra";
1092
+ import * as path15 from "path";
681
1093
  import axios3 from "axios";
682
1094
 
683
1095
  class UpdateChecker {
@@ -686,7 +1098,7 @@ class UpdateChecker {
686
1098
  currentVersion;
687
1099
  constructor(currentVersion) {
688
1100
  const settingsManager = getSettingsManager();
689
- this.cacheFile = path12.join(settingsManager.getStorageDirectory(), "update-cache.json");
1101
+ this.cacheFile = path15.join(settingsManager.getStorageDirectory(), "update-cache.json");
690
1102
  this.currentVersion = currentVersion;
691
1103
  }
692
1104
  static getInstance(currentVersion) {
@@ -697,8 +1109,8 @@ class UpdateChecker {
697
1109
  }
698
1110
  async loadCache() {
699
1111
  try {
700
- if (await fs13.pathExists(this.cacheFile)) {
701
- const cache = await fs13.readJson(this.cacheFile);
1112
+ if (await fs16.pathExists(this.cacheFile)) {
1113
+ const cache = await fs16.readJson(this.cacheFile);
702
1114
  const now = Date.now();
703
1115
  if (cache.lastChecked && now - cache.lastChecked < CACHE_DURATION) {
704
1116
  return cache;
@@ -709,7 +1121,7 @@ class UpdateChecker {
709
1121
  }
710
1122
  async saveCache(info) {
711
1123
  try {
712
- await fs13.outputJson(this.cacheFile, info);
1124
+ await fs16.outputJson(this.cacheFile, info);
713
1125
  } catch (error) {}
714
1126
  }
715
1127
  compareVersions(v1, v2) {
@@ -778,724 +1190,333 @@ var init_update_checker = __esm(() => {
778
1190
  CACHE_DURATION = 24 * 60 * 60 * 1000;
779
1191
  });
780
1192
 
781
- // src/utils/session-manager.ts
782
- var exports_session_manager = {};
783
- __export(exports_session_manager, {
784
- getSessionManager: () => getSessionManager,
785
- SessionManager: () => SessionManager
1193
+ // src/utils/banner.ts
1194
+ var exports_banner = {};
1195
+ __export(exports_banner, {
1196
+ HELP_BANNER: () => HELP_BANNER,
1197
+ BANNER: () => BANNER
786
1198
  });
787
- import * as fs14 from "fs-extra";
788
- import * as path13 from "path";
1199
+ var BANNER = `
1200
+ ╔═══════════════════════════════════════════════════════════════╗
1201
+ ║ ║
1202
+ ║ ███████╗██╗ ██╗██████╗ ███████╗██████╗ ║
1203
+ ║ ██╔════╝██║ ██║██╔══██╗██╔════╝██╔══██╗ ║
1204
+ ║ ███████╗██║ ██║██████╔╝█████╗ ██████╔╝ ║
1205
+ ║ ╚════██║██║ ██║██╔═══╝ ██╔══╝ ██╔══██╗ ║
1206
+ ║ ███████║╚██████╔╝██║ ███████╗██║ ██║ ║
1207
+ ║ ╚══════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ║
1208
+ ║ ║
1209
+ ║ █████╗ ██████╗ ███████╗███╗ ██╗████████╗ ║
1210
+ ║ ██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝ ║
1211
+ ║ ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ║
1212
+ ║ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ║
1213
+ ║ ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ║
1214
+ ║ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ║
1215
+ ║ ║
1216
+ ║ \uD83E\uDD16 AI-Powered Terminal Assistant ║
1217
+ ║ ║
1218
+ ╚═══════════════════════════════════════════════════════════════╝
1219
+ `, HELP_BANNER = `
1220
+ ╔═══════════════════════════════════════════╗
1221
+ ║ \uD83E\uDD16 SUPER AGENT - Help & Usage ║
1222
+ ╚═══════════════════════════════════════════╝
1223
+ `;
789
1224
 
790
- class SessionManager {
1225
+ // src/utils/confirmation-service.ts
1226
+ import { EventEmitter } from "events";
1227
+ import { exec } from "child_process";
1228
+ import { promisify } from "util";
1229
+ var execAsync = promisify(exec);
1230
+
1231
+ class ConfirmationService extends EventEmitter {
791
1232
  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
- }
1233
+ skipConfirmationThisSession = false;
1234
+ pendingConfirmation = null;
1235
+ resolveConfirmation = null;
1236
+ sessionFlags = {
1237
+ fileOperations: false,
1238
+ bashCommands: false,
1239
+ allOperations: false
1240
+ };
799
1241
  static getInstance() {
800
- if (!SessionManager.instance) {
801
- SessionManager.instance = new SessionManager;
1242
+ if (!ConfirmationService.instance) {
1243
+ ConfirmationService.instance = new ConfirmationService;
802
1244
  }
803
- return SessionManager.instance;
804
- }
805
- generateSessionId(workingDir) {
806
- const normalized = path13.normalize(workingDir).toLowerCase();
807
- return Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
1245
+ return ConfirmationService.instance;
808
1246
  }
809
- getSessionFilePath(sessionId) {
810
- return path13.join(this.sessionsDir, `${sessionId}.json`);
1247
+ constructor() {
1248
+ super();
811
1249
  }
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;
1250
+ async requestConfirmation(options, operationType = "file") {
1251
+ if (this.sessionFlags.allOperations || operationType === "file" && this.sessionFlags.fileOperations || operationType === "bash" && this.sessionFlags.bashCommands) {
1252
+ return { confirmed: true };
1253
+ }
1254
+ if (options.showVSCodeOpen) {
1255
+ try {
1256
+ await this.openInVSCode(options.filename);
1257
+ } catch (error) {
1258
+ options.showVSCodeOpen = false;
822
1259
  }
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;
1260
+ }
1261
+ this.pendingConfirmation = new Promise((resolve) => {
1262
+ this.resolveConfirmation = resolve;
1263
+ });
1264
+ setImmediate(() => {
1265
+ this.emit("confirmation-requested", options);
1266
+ });
1267
+ const result = await this.pendingConfirmation;
1268
+ if (result.dontAskAgain) {
1269
+ if (operationType === "file") {
1270
+ this.sessionFlags.fileOperations = true;
1271
+ } else if (operationType === "bash") {
1272
+ this.sessionFlags.bashCommands = true;
1273
+ }
1274
+ }
1275
+ return result;
835
1276
  }
836
- async saveSession(session) {
837
- const sessionFile = this.getSessionFilePath(session.id);
838
- await fs14.outputJson(sessionFile, session, { spaces: 2 });
1277
+ confirmOperation(confirmed, dontAskAgain) {
1278
+ if (this.resolveConfirmation) {
1279
+ this.resolveConfirmation({ confirmed, dontAskAgain });
1280
+ this.resolveConfirmation = null;
1281
+ this.pendingConfirmation = null;
1282
+ }
839
1283
  }
840
- async addMessage(message) {
841
- if (!this.currentSession) {
842
- throw new Error("No active session");
1284
+ rejectOperation(feedback) {
1285
+ if (this.resolveConfirmation) {
1286
+ this.resolveConfirmation({ confirmed: false, feedback });
1287
+ this.resolveConfirmation = null;
1288
+ this.pendingConfirmation = null;
843
1289
  }
844
- this.currentSession.messages.push(message);
845
- this.currentSession.lastAccessed = Date.now();
846
- await this.saveSession(this.currentSession);
847
1290
  }
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) {}
1291
+ async openInVSCode(filename) {
1292
+ const commands = ["code", "code-insiders", "codium"];
1293
+ for (const cmd of commands) {
1294
+ try {
1295
+ await execAsync(`which ${cmd}`);
1296
+ await execAsync(`${cmd} "${filename}"`);
1297
+ return;
1298
+ } catch (error) {
1299
+ continue;
857
1300
  }
858
1301
  }
859
- sessions.sort((a, b) => b.lastAccessed - a.lastAccessed);
860
- return sessions;
1302
+ throw new Error("VS Code not found");
861
1303
  }
862
- async deleteSession(sessionId) {
863
- const sessionFile = this.getSessionFilePath(sessionId);
864
- if (await fs14.pathExists(sessionFile)) {
865
- await fs14.remove(sessionFile);
866
- }
1304
+ isPending() {
1305
+ return this.pendingConfirmation !== null;
867
1306
  }
868
- getCurrentSession() {
869
- return this.currentSession;
1307
+ resetSession() {
1308
+ this.sessionFlags = {
1309
+ fileOperations: false,
1310
+ bashCommands: false,
1311
+ allOperations: false
1312
+ };
870
1313
  }
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;
1314
+ getSessionFlags() {
1315
+ return { ...this.sessionFlags };
1316
+ }
1317
+ setSessionFlag(flagType, value) {
1318
+ this.sessionFlags[flagType] = value;
883
1319
  }
884
1320
  }
885
- function getSessionManager() {
886
- return SessionManager.getInstance();
887
- }
888
- var init_session_manager = __esm(() => {
889
- init_settings_manager();
890
- });
891
1321
 
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";
1322
+ // src/index.ts
1323
+ init_settings_manager();
903
1324
 
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);
917
- });
918
- this.wss = new WebSocketServer({ server: this.httpServer });
919
- this.wss.on("connection", (ws) => {
920
- this.handleWebSocketConnection(ws);
921
- });
1325
+ // src/hooks/use-input-handler.ts
1326
+ init_file_utils();
1327
+
1328
+ // src/utils/text-utils.ts
1329
+ function isWordBoundary(char) {
1330
+ if (!char) {
1331
+ return true;
922
1332
  }
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");
948
- }
949
- } catch (error) {
950
- console.error("Error serving file:", error);
951
- res.writeHead(500);
952
- res.end("Internal Server Error");
953
- }
1333
+ return /\s/.test(char) || /[^\w]/.test(char);
1334
+ }
1335
+ function moveToPreviousWord(text, position) {
1336
+ if (position <= 0) {
1337
+ return 0;
954
1338
  }
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
- });
1339
+ let pos = position - 1;
1340
+ while (pos > 0 && isWordBoundary(text[pos])) {
1341
+ pos--;
985
1342
  }
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
- }));
1016
- }
1343
+ while (pos > 0 && !isWordBoundary(text[pos - 1])) {
1344
+ pos--;
1017
1345
  }
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: [] }));
1025
- return;
1026
- }
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
- }
1346
+ return pos;
1347
+ }
1348
+ function moveToNextWord(text, position) {
1349
+ if (position >= text.length) {
1350
+ return text.length;
1037
1351
  }
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
- }
1352
+ let pos = position;
1353
+ while (pos < text.length && !isWordBoundary(text[pos])) {
1354
+ pos++;
1053
1355
  }
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
- }
1356
+ while (pos < text.length && isWordBoundary(text[pos])) {
1357
+ pos++;
1072
1358
  }
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 }));
1359
+ return pos;
1360
+ }
1361
+ function deleteWordBefore(text, position) {
1362
+ const wordStart = moveToPreviousWord(text, position);
1363
+ const newText = text.slice(0, wordStart) + text.slice(position);
1364
+ return {
1365
+ text: newText,
1366
+ position: wordStart
1367
+ };
1368
+ }
1369
+ function deleteWordAfter(text, position) {
1370
+ const wordEnd = moveToNextWord(text, position);
1371
+ const newText = text.slice(0, position) + text.slice(wordEnd);
1372
+ return {
1373
+ text: newText,
1374
+ position
1375
+ };
1376
+ }
1377
+ function moveToLineStart(text, position) {
1378
+ const beforeCursor = text.slice(0, position);
1379
+ const lastNewlineIndex = beforeCursor.lastIndexOf(`
1380
+ `);
1381
+ return lastNewlineIndex === -1 ? 0 : lastNewlineIndex + 1;
1382
+ }
1383
+ function moveToLineEnd(text, position) {
1384
+ const afterCursor = text.slice(position);
1385
+ const nextNewlineIndex = afterCursor.indexOf(`
1386
+ `);
1387
+ return nextNewlineIndex === -1 ? text.length : position + nextNewlineIndex;
1388
+ }
1389
+ function deleteCharBefore(text, position) {
1390
+ if (position <= 0) {
1391
+ return { text, position };
1392
+ }
1393
+ let deleteCount = 1;
1394
+ const charBefore = text.charAt(position - 1);
1395
+ if (position >= 2) {
1396
+ const charBeforeBefore = text.charAt(position - 2);
1397
+ if (charBeforeBefore >= "\uD800" && charBeforeBefore <= "\uDBFF" && charBefore >= "\uDC00" && charBefore <= "\uDFFF") {
1398
+ deleteCount = 2;
1093
1399
  }
1094
1400
  }
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) {}
1401
+ const newText = text.slice(0, position - deleteCount) + text.slice(position);
1402
+ return {
1403
+ text: newText,
1404
+ position: position - deleteCount
1405
+ };
1406
+ }
1407
+ function deleteCharAfter(text, position) {
1408
+ if (position >= text.length) {
1409
+ return { text, position };
1109
1410
  }
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");
1411
+ let deleteCount = 1;
1412
+ const charAfter = text.charAt(position);
1413
+ if (position + 1 < text.length) {
1414
+ const charAfterAfter = text.charAt(position + 1);
1415
+ if (charAfter >= "\uD800" && charAfter <= "\uDBFF" && charAfterAfter >= "\uDC00" && charAfterAfter <= "\uDFFF") {
1416
+ deleteCount = 2;
1417
+ }
1138
1418
  }
1419
+ const newText = text.slice(0, position) + text.slice(position + deleteCount);
1420
+ return {
1421
+ text: newText,
1422
+ position
1423
+ };
1139
1424
  }
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
1425
+ function insertText(text, position, insert) {
1426
+ const newText = text.slice(0, position) + insert + text.slice(position);
1427
+ return {
1428
+ text: newText,
1429
+ position: position + insert.length
1158
1430
  };
1159
- static getInstance() {
1160
- if (!ConfirmationService.instance) {
1161
- ConfirmationService.instance = new ConfirmationService;
1431
+ }
1432
+
1433
+ // src/hooks/use-input-history.ts
1434
+ import { useState, useCallback } from "react";
1435
+ function useInputHistory() {
1436
+ const [history, setHistory] = useState([]);
1437
+ const [currentIndex, setCurrentIndex] = useState(-1);
1438
+ const [originalInput, setOriginalInput] = useState("");
1439
+ const addToHistory = useCallback((input) => {
1440
+ if (input.trim() && !history.includes(input.trim())) {
1441
+ setHistory((prev) => [...prev, input.trim()]);
1162
1442
  }
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 };
1443
+ setCurrentIndex(-1);
1444
+ setOriginalInput("");
1445
+ }, [history]);
1446
+ const navigateHistory = useCallback((direction) => {
1447
+ if (history.length === 0) {
1448
+ return null;
1171
1449
  }
1172
- if (options.showVSCodeOpen) {
1173
- try {
1174
- await this.openInVSCode(options.filename);
1175
- } catch (error) {
1176
- options.showVSCodeOpen = false;
1450
+ let newIndex;
1451
+ if (direction === "up") {
1452
+ if (currentIndex === -1) {
1453
+ newIndex = history.length - 1;
1454
+ } else {
1455
+ newIndex = Math.max(0, currentIndex - 1);
1177
1456
  }
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;
1457
+ } else {
1458
+ if (currentIndex === -1) {
1459
+ return null;
1460
+ } else if (currentIndex === history.length - 1) {
1461
+ newIndex = -1;
1462
+ return originalInput;
1463
+ } else {
1464
+ newIndex = Math.min(history.length - 1, currentIndex + 1);
1191
1465
  }
1192
1466
  }
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
- }
1467
+ setCurrentIndex(newIndex);
1468
+ return newIndex === -1 ? originalInput : history[newIndex];
1469
+ }, [history, currentIndex, originalInput]);
1470
+ const getCurrentHistoryIndex = useCallback(() => currentIndex, [currentIndex]);
1471
+ const resetHistory = useCallback(() => {
1472
+ setHistory([]);
1473
+ setCurrentIndex(-1);
1474
+ setOriginalInput("");
1475
+ }, []);
1476
+ const isNavigatingHistory = useCallback(() => currentIndex !== -1, [currentIndex]);
1477
+ const setOriginalInputCallback = useCallback((input) => {
1478
+ if (currentIndex === -1) {
1479
+ setOriginalInput(input);
1219
1480
  }
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 };
1234
- }
1235
- setSessionFlag(flagType, value) {
1236
- this.sessionFlags[flagType] = value;
1237
- }
1481
+ }, [currentIndex]);
1482
+ return {
1483
+ addToHistory,
1484
+ navigateHistory,
1485
+ getCurrentHistoryIndex,
1486
+ resetHistory,
1487
+ isNavigatingHistory,
1488
+ setOriginalInput: setOriginalInputCallback
1489
+ };
1238
1490
  }
1239
1491
 
1240
- // src/index.ts
1241
- init_settings_manager();
1242
-
1243
- // src/utils/file-utils.ts
1244
- import * as fs2 from "fs-extra";
1245
- import * as path2 from "path";
1246
- async function listFilesRecursive(dir, baseDir = dir, maxDepth = 3) {
1247
- const result = [];
1248
- try {
1249
- const entries = await fs2.readdir(dir, { withFileTypes: true });
1250
- for (const entry of entries) {
1251
- const fullPath = path2.join(dir, entry.name);
1252
- const relativePath = path2.relative(baseDir, fullPath);
1253
- const isIgnored = [
1254
- "node_modules",
1255
- ".git",
1256
- "dist",
1257
- "build",
1258
- ".next",
1259
- "target",
1260
- "vendor"
1261
- ].includes(entry.name);
1262
- if (isIgnored) {
1263
- continue;
1264
- }
1265
- if (entry.name.startsWith(".") && entry.name !== ".env") {
1266
- continue;
1267
- }
1268
- result.push({
1269
- name: entry.name,
1270
- path: relativePath,
1271
- isDirectory: entry.isDirectory()
1272
- });
1273
- if (entry.isDirectory() && maxDepth > 0) {
1274
- const subFiles = await listFilesRecursive(fullPath, baseDir, maxDepth - 1);
1275
- result.push(...subFiles);
1276
- }
1277
- }
1278
- } catch (error) {}
1279
- return result;
1280
- }
1281
- function filterFileEntries(entries, query) {
1282
- if (!query) {
1283
- return entries.slice(0, 20);
1284
- }
1285
- const lowerQuery = query.toLowerCase();
1286
- return entries.filter((e) => e.path.toLowerCase().includes(lowerQuery)).sort((a, b) => {
1287
- const aLower = a.name.toLowerCase();
1288
- const bLower = b.name.toLowerCase();
1289
- if (aLower === lowerQuery && bLower !== lowerQuery) {
1290
- return -1;
1291
- }
1292
- if (bLower === lowerQuery && aLower !== lowerQuery) {
1293
- return 1;
1294
- }
1295
- const aPathLower = a.path.toLowerCase();
1296
- const bPathLower = b.path.toLowerCase();
1297
- if (aPathLower.startsWith(lowerQuery) && !bPathLower.startsWith(lowerQuery)) {
1298
- return -1;
1492
+ // src/hooks/use-enhanced-input.ts
1493
+ import { useCallback as useCallback2, useRef, useState as useState2 } from "react";
1494
+ function useEnhancedInput({
1495
+ onSubmit,
1496
+ onEscape,
1497
+ onSpecialKey,
1498
+ disabled = false,
1499
+ multiline = false
1500
+ } = {}) {
1501
+ const [input, setInputState] = useState2("");
1502
+ const [cursorPosition, setCursorPositionState] = useState2(0);
1503
+ const isMultilineRef = useRef(multiline);
1504
+ const {
1505
+ addToHistory,
1506
+ navigateHistory,
1507
+ resetHistory,
1508
+ setOriginalInput,
1509
+ isNavigatingHistory
1510
+ } = useInputHistory();
1511
+ const setInput = useCallback2((text, newCursorPos) => {
1512
+ setInputState(text);
1513
+ if (newCursorPos !== undefined) {
1514
+ setCursorPositionState(Math.max(0, Math.min(text.length, newCursorPos)));
1515
+ } else {
1516
+ setCursorPositionState(Math.min(text.length, cursorPosition));
1299
1517
  }
1300
- if (bPathLower.startsWith(lowerQuery) && !aPathLower.startsWith(lowerQuery)) {
1301
- return 1;
1302
- }
1303
- return a.path.length - b.path.length;
1304
- }).slice(0, 20);
1305
- }
1306
-
1307
- // src/utils/text-utils.ts
1308
- function isWordBoundary(char) {
1309
- if (!char) {
1310
- return true;
1311
- }
1312
- return /\s/.test(char) || /[^\w]/.test(char);
1313
- }
1314
- function moveToPreviousWord(text, position) {
1315
- if (position <= 0) {
1316
- return 0;
1317
- }
1318
- let pos = position - 1;
1319
- while (pos > 0 && isWordBoundary(text[pos])) {
1320
- pos--;
1321
- }
1322
- while (pos > 0 && !isWordBoundary(text[pos - 1])) {
1323
- pos--;
1324
- }
1325
- return pos;
1326
- }
1327
- function moveToNextWord(text, position) {
1328
- if (position >= text.length) {
1329
- return text.length;
1330
- }
1331
- let pos = position;
1332
- while (pos < text.length && !isWordBoundary(text[pos])) {
1333
- pos++;
1334
- }
1335
- while (pos < text.length && isWordBoundary(text[pos])) {
1336
- pos++;
1337
- }
1338
- return pos;
1339
- }
1340
- function deleteWordBefore(text, position) {
1341
- const wordStart = moveToPreviousWord(text, position);
1342
- const newText = text.slice(0, wordStart) + text.slice(position);
1343
- return {
1344
- text: newText,
1345
- position: wordStart
1346
- };
1347
- }
1348
- function deleteWordAfter(text, position) {
1349
- const wordEnd = moveToNextWord(text, position);
1350
- const newText = text.slice(0, position) + text.slice(wordEnd);
1351
- return {
1352
- text: newText,
1353
- position
1354
- };
1355
- }
1356
- function moveToLineStart(text, position) {
1357
- const beforeCursor = text.slice(0, position);
1358
- const lastNewlineIndex = beforeCursor.lastIndexOf(`
1359
- `);
1360
- return lastNewlineIndex === -1 ? 0 : lastNewlineIndex + 1;
1361
- }
1362
- function moveToLineEnd(text, position) {
1363
- const afterCursor = text.slice(position);
1364
- const nextNewlineIndex = afterCursor.indexOf(`
1365
- `);
1366
- return nextNewlineIndex === -1 ? text.length : position + nextNewlineIndex;
1367
- }
1368
- function deleteCharBefore(text, position) {
1369
- if (position <= 0) {
1370
- return { text, position };
1371
- }
1372
- let deleteCount = 1;
1373
- const charBefore = text.charAt(position - 1);
1374
- if (position >= 2) {
1375
- const charBeforeBefore = text.charAt(position - 2);
1376
- if (charBeforeBefore >= "\uD800" && charBeforeBefore <= "\uDBFF" && charBefore >= "\uDC00" && charBefore <= "\uDFFF") {
1377
- deleteCount = 2;
1378
- }
1379
- }
1380
- const newText = text.slice(0, position - deleteCount) + text.slice(position);
1381
- return {
1382
- text: newText,
1383
- position: position - deleteCount
1384
- };
1385
- }
1386
- function deleteCharAfter(text, position) {
1387
- if (position >= text.length) {
1388
- return { text, position };
1389
- }
1390
- let deleteCount = 1;
1391
- const charAfter = text.charAt(position);
1392
- if (position + 1 < text.length) {
1393
- const charAfterAfter = text.charAt(position + 1);
1394
- if (charAfter >= "\uD800" && charAfter <= "\uDBFF" && charAfterAfter >= "\uDC00" && charAfterAfter <= "\uDFFF") {
1395
- deleteCount = 2;
1396
- }
1397
- }
1398
- const newText = text.slice(0, position) + text.slice(position + deleteCount);
1399
- return {
1400
- text: newText,
1401
- position
1402
- };
1403
- }
1404
- function insertText(text, position, insert) {
1405
- const newText = text.slice(0, position) + insert + text.slice(position);
1406
- return {
1407
- text: newText,
1408
- position: position + insert.length
1409
- };
1410
- }
1411
-
1412
- // src/hooks/use-input-history.ts
1413
- import { useState, useCallback } from "react";
1414
- function useInputHistory() {
1415
- const [history, setHistory] = useState([]);
1416
- const [currentIndex, setCurrentIndex] = useState(-1);
1417
- const [originalInput, setOriginalInput] = useState("");
1418
- const addToHistory = useCallback((input) => {
1419
- if (input.trim() && !history.includes(input.trim())) {
1420
- setHistory((prev) => [...prev, input.trim()]);
1421
- }
1422
- setCurrentIndex(-1);
1423
- setOriginalInput("");
1424
- }, [history]);
1425
- const navigateHistory = useCallback((direction) => {
1426
- if (history.length === 0) {
1427
- return null;
1428
- }
1429
- let newIndex;
1430
- if (direction === "up") {
1431
- if (currentIndex === -1) {
1432
- newIndex = history.length - 1;
1433
- } else {
1434
- newIndex = Math.max(0, currentIndex - 1);
1435
- }
1436
- } else {
1437
- if (currentIndex === -1) {
1438
- return null;
1439
- } else if (currentIndex === history.length - 1) {
1440
- newIndex = -1;
1441
- return originalInput;
1442
- } else {
1443
- newIndex = Math.min(history.length - 1, currentIndex + 1);
1444
- }
1445
- }
1446
- setCurrentIndex(newIndex);
1447
- return newIndex === -1 ? originalInput : history[newIndex];
1448
- }, [history, currentIndex, originalInput]);
1449
- const getCurrentHistoryIndex = useCallback(() => currentIndex, [currentIndex]);
1450
- const resetHistory = useCallback(() => {
1451
- setHistory([]);
1452
- setCurrentIndex(-1);
1453
- setOriginalInput("");
1454
- }, []);
1455
- const isNavigatingHistory = useCallback(() => currentIndex !== -1, [currentIndex]);
1456
- const setOriginalInputCallback = useCallback((input) => {
1457
- if (currentIndex === -1) {
1458
- setOriginalInput(input);
1459
- }
1460
- }, [currentIndex]);
1461
- return {
1462
- addToHistory,
1463
- navigateHistory,
1464
- getCurrentHistoryIndex,
1465
- resetHistory,
1466
- isNavigatingHistory,
1467
- setOriginalInput: setOriginalInputCallback
1468
- };
1469
- }
1470
-
1471
- // src/hooks/use-enhanced-input.ts
1472
- import { useCallback as useCallback2, useRef, useState as useState2 } from "react";
1473
- function useEnhancedInput({
1474
- onSubmit,
1475
- onEscape,
1476
- onSpecialKey,
1477
- disabled = false,
1478
- multiline = false
1479
- } = {}) {
1480
- const [input, setInputState] = useState2("");
1481
- const [cursorPosition, setCursorPositionState] = useState2(0);
1482
- const isMultilineRef = useRef(multiline);
1483
- const {
1484
- addToHistory,
1485
- navigateHistory,
1486
- resetHistory,
1487
- setOriginalInput,
1488
- isNavigatingHistory
1489
- } = useInputHistory();
1490
- const setInput = useCallback2((text, newCursorPos) => {
1491
- setInputState(text);
1492
- if (newCursorPos !== undefined) {
1493
- setCursorPositionState(Math.max(0, Math.min(text.length, newCursorPos)));
1494
- } else {
1495
- setCursorPositionState(Math.min(text.length, cursorPosition));
1496
- }
1497
- if (!isNavigatingHistory()) {
1498
- setOriginalInput(text);
1518
+ if (!isNavigatingHistory()) {
1519
+ setOriginalInput(text);
1499
1520
  }
1500
1521
  }, [cursorPosition, isNavigatingHistory, setOriginalInput]);
1501
1522
  const setCursorPosition = useCallback2((position) => {
@@ -1747,9 +1768,9 @@ function CommandSuggestions({
1747
1768
 
1748
1769
  // src/utils/model-config.ts
1749
1770
  init_settings_manager();
1750
- function loadModelConfig() {
1771
+ function loadModelConfig(providerId) {
1751
1772
  const manager = getSettingsManager();
1752
- const models = manager.getAvailableModels();
1773
+ const models = manager.getAvailableModels(providerId);
1753
1774
  return models.map((model) => ({
1754
1775
  model: model.trim()
1755
1776
  }));
@@ -2721,7 +2742,7 @@ function getChatManager() {
2721
2742
  }
2722
2743
 
2723
2744
  // src/hooks/use-input-handler.ts
2724
- import * as fs6 from "fs-extra";
2745
+ import * as fs8 from "fs-extra";
2725
2746
  function useInputHandler({
2726
2747
  agent,
2727
2748
  chatHistory,
@@ -2863,6 +2884,7 @@ function useInputHandler({
2863
2884
  if (providers.length > 0) {
2864
2885
  const selectedProviderId = providers[selectedProviderIndex];
2865
2886
  manager.updateUserSetting("active_provider", selectedProviderId);
2887
+ setActiveProvider(selectedProviderId);
2866
2888
  setChatHistory((prev) => [
2867
2889
  ...prev,
2868
2890
  {
@@ -2879,6 +2901,24 @@ function useInputHandler({
2879
2901
  setShowProviderSelection(false);
2880
2902
  return true;
2881
2903
  }
2904
+ if (char === "e" || char === "E") {
2905
+ if (providers.length > 0) {
2906
+ const selectedProviderId = providers[selectedProviderIndex];
2907
+ const manager2 = getSettingsManager();
2908
+ const currentKey = manager2.getUserSetting("providers")?.[selectedProviderId]?.api_key || "";
2909
+ setChatHistory((prev) => [
2910
+ ...prev,
2911
+ {
2912
+ type: "assistant",
2913
+ content: `\uD83D\uDCDD Editing API key for ${selectedProviderId}. Press Enter after pasting key.`,
2914
+ timestamp: new Date
2915
+ }
2916
+ ]);
2917
+ setShowProviderSelection(false);
2918
+ setInput(`/provider set-key ${selectedProviderId} `);
2919
+ }
2920
+ return true;
2921
+ }
2882
2922
  return true;
2883
2923
  }
2884
2924
  if (showConfigViewer) {
@@ -3074,13 +3114,17 @@ function useInputHandler({
3074
3114
  description: "Manage plugins (list, install, remove)"
3075
3115
  },
3076
3116
  { command: "/commit-and-push", description: "AI commit & push to remote" },
3117
+ {
3118
+ command: "/import <type> <source>",
3119
+ description: "Import resources (agents, skills, hooks)"
3120
+ },
3077
3121
  { command: "/exit", description: "Exit the application" }
3078
3122
  ];
3079
3123
  const [activeProvider, setActiveProvider] = useState3(() => {
3080
3124
  return getSettingsManager().loadUserSettings().active_provider;
3081
3125
  });
3082
3126
  const availableModels = useMemo2(() => {
3083
- return loadModelConfig();
3127
+ return loadModelConfig(activeProvider);
3084
3128
  }, [activeProvider]);
3085
3129
  const handleDirectCommand = async (input2) => {
3086
3130
  const trimmedInput = input2.trim();
@@ -3146,6 +3190,64 @@ Config Commands:
3146
3190
  clearInput();
3147
3191
  return true;
3148
3192
  }
3193
+ if (trimmedInput === "/provider config") {
3194
+ setChatHistory((prev) => [
3195
+ ...prev,
3196
+ {
3197
+ type: "assistant",
3198
+ content: "⚠️ Interactive configuration cannot be run inside the chat session.\n\nPlease run `super-agent provider config` in a separate terminal, or use:\n`/provider set-key <provider> <key>` to set an API key directly.",
3199
+ timestamp: new Date
3200
+ }
3201
+ ]);
3202
+ clearInput();
3203
+ return true;
3204
+ }
3205
+ if (trimmedInput.startsWith("/provider set-key ")) {
3206
+ const args = trimmedInput.replace("/provider set-key ", "").trim().split(" ");
3207
+ const providerId = args[0];
3208
+ const key = args.slice(1).join(" ");
3209
+ if (!providerId || !key) {
3210
+ setChatHistory((prev) => [
3211
+ ...prev,
3212
+ {
3213
+ type: "assistant",
3214
+ content: "❌ Usage: /provider set-key <provider> <api_key>",
3215
+ timestamp: new Date
3216
+ }
3217
+ ]);
3218
+ clearInput();
3219
+ return true;
3220
+ }
3221
+ const manager = getSettingsManager();
3222
+ const settings = manager.loadUserSettings();
3223
+ if (settings.providers && settings.providers[providerId]) {
3224
+ const newProviders = { ...settings.providers };
3225
+ newProviders[providerId] = {
3226
+ ...newProviders[providerId],
3227
+ api_key: key
3228
+ };
3229
+ manager.updateUserSetting("providers", newProviders);
3230
+ setChatHistory((prev) => [
3231
+ ...prev,
3232
+ {
3233
+ type: "assistant",
3234
+ content: `✅ API Key for ${providerId} updated.`,
3235
+ timestamp: new Date
3236
+ }
3237
+ ]);
3238
+ } else {
3239
+ setChatHistory((prev) => [
3240
+ ...prev,
3241
+ {
3242
+ type: "assistant",
3243
+ content: `❌ Provider '${providerId}' not found.`,
3244
+ timestamp: new Date
3245
+ }
3246
+ ]);
3247
+ }
3248
+ clearInput();
3249
+ return true;
3250
+ }
3149
3251
  if (trimmedInput.startsWith("/provider use ")) {
3150
3252
  const providerId = trimmedInput.replace("/provider use ", "").trim();
3151
3253
  const manager = getSettingsManager();
@@ -3319,10 +3421,153 @@ ${chats.length ? chats.map((c) => `- ${c}`).join(`
3319
3421
  clearInput();
3320
3422
  return true;
3321
3423
  }
3322
- if (trimmedInput.startsWith("/plugin ")) {
3323
- const args = trimmedInput.replace("/plugin ", "").split(" ");
3324
- const action = args[0];
3325
- const pluginManager = getPluginManager();
3424
+ if (trimmedInput.startsWith("/import ")) {
3425
+ const args = trimmedInput.replace("/import ", "").split(" ");
3426
+ const type = args[0];
3427
+ const source = args[1];
3428
+ if (!type || !source) {
3429
+ setChatHistory((prev) => [
3430
+ ...prev,
3431
+ {
3432
+ type: "assistant",
3433
+ content: `❌ Usage: /import <type> <source>
3434
+ Types: agents, skills, hooks
3435
+ Sources: gemini, claude, kilo, or path`,
3436
+ timestamp: new Date
3437
+ }
3438
+ ]);
3439
+ clearInput();
3440
+ return true;
3441
+ }
3442
+ setIsProcessing(true);
3443
+ setChatHistory((prev) => [
3444
+ ...prev,
3445
+ {
3446
+ type: "assistant",
3447
+ content: `Importing ${type} from ${source}...`,
3448
+ timestamp: new Date
3449
+ }
3450
+ ]);
3451
+ try {
3452
+ const { resolveSourcePath: resolveSourcePath2 } = await Promise.resolve().then(() => (init_file_utils(), exports_file_utils));
3453
+ const { AgentsManager: AgentsManager2 } = await Promise.resolve().then(() => (init_manager(), exports_manager));
3454
+ const { SkillsManager: SkillsManager2 } = await Promise.resolve().then(() => (init_manager2(), exports_manager2));
3455
+ const { getSettingsManager: getSettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), exports_settings_manager));
3456
+ const fs9 = await import("fs-extra");
3457
+ const path8 = await import("path");
3458
+ const sourcePath = resolveSourcePath2(source);
3459
+ if (type === "agents") {
3460
+ const agentsDir = path8.join(sourcePath, "agents");
3461
+ if (!await fs9.pathExists(agentsDir)) {
3462
+ throw new Error(`Agents directory not found at ${agentsDir}`);
3463
+ }
3464
+ const files = await fs9.readdir(agentsDir);
3465
+ const manager = AgentsManager2.getInstance();
3466
+ let count = 0;
3467
+ for (const file of files) {
3468
+ if (file.endsWith(".json")) {
3469
+ try {
3470
+ const content = await fs9.readJson(path8.join(agentsDir, file));
3471
+ const agentConfig = {
3472
+ name: content.name || path8.parse(file).name,
3473
+ role: content.role || "Assistant",
3474
+ description: content.description || "Imported agent",
3475
+ model: content.model,
3476
+ tools: content.tools,
3477
+ temperature: content.temperature,
3478
+ systemPrompt: content.systemPrompt || content.system_prompt || content.prompt
3479
+ };
3480
+ await manager.createAgent(agentConfig);
3481
+ count++;
3482
+ } catch (e) {}
3483
+ }
3484
+ }
3485
+ setChatHistory((prev) => [
3486
+ ...prev,
3487
+ {
3488
+ type: "assistant",
3489
+ content: `✅ Imported ${count} agents.`,
3490
+ timestamp: new Date
3491
+ }
3492
+ ]);
3493
+ } else if (type === "skills") {
3494
+ const skillsDir = path8.join(sourcePath, "skills");
3495
+ if (!await fs9.pathExists(skillsDir)) {
3496
+ throw new Error(`Skills directory not found at ${skillsDir}`);
3497
+ }
3498
+ const files = await fs9.readdir(skillsDir);
3499
+ const manager = SkillsManager2.getInstance();
3500
+ let count = 0;
3501
+ for (const file of files) {
3502
+ if (file.endsWith(".ts") || file.endsWith(".js")) {
3503
+ try {
3504
+ const content = await fs9.readFile(path8.join(skillsDir, file), "utf-8");
3505
+ const name = path8.parse(file).name;
3506
+ await manager.saveSkill(name, content);
3507
+ count++;
3508
+ } catch (e) {}
3509
+ }
3510
+ }
3511
+ setChatHistory((prev) => [
3512
+ ...prev,
3513
+ {
3514
+ type: "assistant",
3515
+ content: `✅ Imported ${count} skills.`,
3516
+ timestamp: new Date
3517
+ }
3518
+ ]);
3519
+ } else if (type === "hooks") {
3520
+ const settingsFile = source.toLowerCase() === "claude" ? "settings.local.json" : "settings.json";
3521
+ const fullPath = path8.join(sourcePath, settingsFile);
3522
+ if (!await fs9.pathExists(fullPath)) {
3523
+ throw new Error(`Settings file not found at ${fullPath}`);
3524
+ }
3525
+ const settings = await fs9.readJson(fullPath);
3526
+ if (settings.hooks) {
3527
+ const manager = getSettingsManager2();
3528
+ const currentHooks = manager.getUserSetting("hooks") || {};
3529
+ const mergedHooks = { ...currentHooks, ...settings.hooks };
3530
+ manager.updateUserSetting("hooks", mergedHooks);
3531
+ setChatHistory((prev) => [
3532
+ ...prev,
3533
+ {
3534
+ type: "assistant",
3535
+ content: `✅ Imported ${Object.keys(settings.hooks).length} hooks.`,
3536
+ timestamp: new Date
3537
+ }
3538
+ ]);
3539
+ } else {
3540
+ setChatHistory((prev) => [
3541
+ ...prev,
3542
+ {
3543
+ type: "assistant",
3544
+ content: "⚠️ No hooks found in settings file.",
3545
+ timestamp: new Date
3546
+ }
3547
+ ]);
3548
+ }
3549
+ } else {
3550
+ throw new Error(`Unknown import type: ${type}`);
3551
+ }
3552
+ } catch (error) {
3553
+ setChatHistory((prev) => [
3554
+ ...prev,
3555
+ {
3556
+ type: "assistant",
3557
+ content: `❌ Import failed: ${error.message}`,
3558
+ timestamp: new Date
3559
+ }
3560
+ ]);
3561
+ } finally {
3562
+ setIsProcessing(false);
3563
+ }
3564
+ clearInput();
3565
+ return true;
3566
+ }
3567
+ if (trimmedInput.startsWith("/plugin ")) {
3568
+ const args = trimmedInput.replace("/plugin ", "").split(" ");
3569
+ const action = args[0];
3570
+ const pluginManager = getPluginManager();
3326
3571
  try {
3327
3572
  if (action === "list") {
3328
3573
  const plugins = pluginManager.getPlugins();
@@ -3735,9 +3980,9 @@ ${commitMessage}`
3735
3980
  for (const mention of mentionMatches) {
3736
3981
  const filePath = mention.slice(1);
3737
3982
  try {
3738
- const stats = await fs6.stat(filePath);
3983
+ const stats = await fs8.stat(filePath);
3739
3984
  if (stats.isFile()) {
3740
- const content = await fs6.readFile(filePath, "utf-8");
3985
+ const content = await fs8.readFile(filePath, "utf-8");
3741
3986
  resolvedInput = resolvedInput.replace(mention, `
3742
3987
 
3743
3988
  --- FILE: ${filePath} ---
@@ -3888,6 +4133,7 @@ ${structure}
3888
4133
  }
3889
4134
 
3890
4135
  // src/ui/components/mention-suggestions.tsx
4136
+ init_file_utils();
3891
4137
  import { useMemo as useMemo3 } from "react";
3892
4138
  import { Box as Box2, Text as Text2 } from "ink";
3893
4139
  import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
@@ -4665,6 +4911,7 @@ function LoadingSpinner({
4665
4911
  }
4666
4912
 
4667
4913
  // src/ui/components/command-palette.tsx
4914
+ init_file_utils();
4668
4915
  import { useMemo as useMemo4 } from "react";
4669
4916
  import { Box as Box9, Text as Text8 } from "ink";
4670
4917
  import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
@@ -5303,8 +5550,8 @@ class ConfirmationTool {
5303
5550
  }
5304
5551
  }
5305
5552
  // src/tools/morph-editor.ts
5306
- import * as path6 from "path";
5307
- import fs7 from "fs-extra";
5553
+ import * as path8 from "path";
5554
+ import fs9 from "fs-extra";
5308
5555
  import axios2 from "axios";
5309
5556
 
5310
5557
  class MorphEditorTool {
@@ -5319,8 +5566,8 @@ class MorphEditorTool {
5319
5566
  }
5320
5567
  async editFile(targetFile, instructions, codeEdit) {
5321
5568
  try {
5322
- const resolvedPath = path6.resolve(targetFile);
5323
- if (!await fs7.pathExists(resolvedPath)) {
5569
+ const resolvedPath = path8.resolve(targetFile);
5570
+ if (!await fs9.pathExists(resolvedPath)) {
5324
5571
  return {
5325
5572
  success: false,
5326
5573
  error: `File not found: ${targetFile}`
@@ -5332,7 +5579,7 @@ class MorphEditorTool {
5332
5579
  error: "MORPH_API_KEY not configured. Please set your Morph API key."
5333
5580
  };
5334
5581
  }
5335
- const initialCode = await fs7.readFile(resolvedPath, "utf-8");
5582
+ const initialCode = await fs9.readFile(resolvedPath, "utf-8");
5336
5583
  const sessionFlags = this.confirmationService.getSessionFlags();
5337
5584
  if (!sessionFlags.fileOperations && !sessionFlags.allOperations) {
5338
5585
  const confirmationResult = await this.confirmationService.requestConfirmation({
@@ -5352,7 +5599,7 @@ ${codeEdit}`
5352
5599
  }
5353
5600
  }
5354
5601
  const mergedCode = await this.callMorphApply(instructions, initialCode, codeEdit);
5355
- await fs7.writeFile(resolvedPath, mergedCode, "utf-8");
5602
+ await fs9.writeFile(resolvedPath, mergedCode, "utf-8");
5356
5603
  const oldLines = initialCode.split(`
5357
5604
  `);
5358
5605
  const newLines = mergedCode.split(`
@@ -5535,11 +5782,11 @@ ${codeEdit}`
5535
5782
  }
5536
5783
  async view(filePath, viewRange) {
5537
5784
  try {
5538
- const resolvedPath = path6.resolve(filePath);
5539
- if (await fs7.pathExists(resolvedPath)) {
5540
- const stats = await fs7.stat(resolvedPath);
5785
+ const resolvedPath = path8.resolve(filePath);
5786
+ if (await fs9.pathExists(resolvedPath)) {
5787
+ const stats = await fs9.stat(resolvedPath);
5541
5788
  if (stats.isDirectory()) {
5542
- const files = await fs7.readdir(resolvedPath);
5789
+ const files = await fs9.readdir(resolvedPath);
5543
5790
  return {
5544
5791
  success: true,
5545
5792
  output: `Directory contents of ${filePath}:
@@ -5547,7 +5794,7 @@ ${files.join(`
5547
5794
  `)}`
5548
5795
  };
5549
5796
  }
5550
- const content = await fs7.readFile(resolvedPath, "utf-8");
5797
+ const content = await fs9.readFile(resolvedPath, "utf-8");
5551
5798
  const lines = content.split(`
5552
5799
  `);
5553
5800
  if (viewRange) {
@@ -5593,8 +5840,8 @@ ${numberedLines}${additionalLinesMessage}`
5593
5840
  }
5594
5841
  }
5595
5842
  // src/tools/project-map.ts
5596
- import * as path7 from "path";
5597
- import fs8 from "fs-extra";
5843
+ import * as path9 from "path";
5844
+ import fs10 from "fs-extra";
5598
5845
 
5599
5846
  class ProjectMapTool {
5600
5847
  currentDirectory = process.cwd();
@@ -5628,7 +5875,7 @@ Important Files:
5628
5875
  }
5629
5876
  let result = "";
5630
5877
  try {
5631
- const entries = await fs8.readdir(dir, { withFileTypes: true });
5878
+ const entries = await fs10.readdir(dir, { withFileTypes: true });
5632
5879
  const sortedEntries = entries.sort((a, b) => {
5633
5880
  if (a.isDirectory() && !b.isDirectory()) {
5634
5881
  return -1;
@@ -5656,7 +5903,7 @@ Important Files:
5656
5903
  if (entry.isDirectory()) {
5657
5904
  result += `${indent}\uD83D\uDCC1 ${entry.name}/
5658
5905
  `;
5659
- result += await this.generateTree(path7.join(dir, entry.name), maxDepth, currentDepth + 1);
5906
+ result += await this.generateTree(path9.join(dir, entry.name), maxDepth, currentDepth + 1);
5660
5907
  } else {
5661
5908
  result += `${indent}\uD83D\uDCC4 ${entry.name}
5662
5909
  `;
@@ -5678,8 +5925,8 @@ Important Files:
5678
5925
  ];
5679
5926
  const found = [];
5680
5927
  for (const pattern of importantPatterns) {
5681
- const fullPath = path7.join(this.currentDirectory, pattern);
5682
- if (await fs8.pathExists(fullPath)) {
5928
+ const fullPath = path9.join(this.currentDirectory, pattern);
5929
+ if (await fs10.pathExists(fullPath)) {
5683
5930
  found.push(pattern);
5684
5931
  }
5685
5932
  }
@@ -5692,8 +5939,8 @@ Important Files:
5692
5939
  // src/tools/search.ts
5693
5940
  init_indexer();
5694
5941
  import { spawn } from "child_process";
5695
- import * as path9 from "path";
5696
- import fs10 from "fs-extra";
5942
+ import * as path11 from "path";
5943
+ import fs12 from "fs-extra";
5697
5944
 
5698
5945
  class SearchTool {
5699
5946
  confirmationService = ConfirmationService.getInstance();
@@ -5722,7 +5969,7 @@ class SearchTool {
5722
5969
  const searchPattern = query.toLowerCase();
5723
5970
  fileResults = entries.filter((e) => e.path.toLowerCase().includes(searchPattern)).map((e) => ({
5724
5971
  path: e.path,
5725
- name: path9.basename(e.path),
5972
+ name: path11.basename(e.path),
5726
5973
  score: 10
5727
5974
  }));
5728
5975
  } else {
@@ -5846,13 +6093,13 @@ class SearchTool {
5846
6093
  return;
5847
6094
  }
5848
6095
  try {
5849
- const entries = await fs10.readdir(dir, { withFileTypes: true });
6096
+ const entries = await fs12.readdir(dir, { withFileTypes: true });
5850
6097
  for (const entry of entries) {
5851
6098
  if (files.length >= maxResults) {
5852
6099
  break;
5853
6100
  }
5854
- const fullPath = path9.join(dir, entry.name);
5855
- const relativePath = path9.relative(this.currentDirectory, fullPath);
6101
+ const fullPath = path11.join(dir, entry.name);
6102
+ const relativePath = path11.relative(this.currentDirectory, fullPath);
5856
6103
  if (!options.includeHidden && entry.name.startsWith(".")) {
5857
6104
  continue;
5858
6105
  }
@@ -5951,19 +6198,19 @@ class SearchTool {
5951
6198
  }
5952
6199
  // src/tools/text-editor.ts
5953
6200
  import { writeFile as writeFilePromise } from "fs/promises";
5954
- import * as path10 from "path";
5955
- import fs11 from "fs-extra";
6201
+ import * as path12 from "path";
6202
+ import fs13 from "fs-extra";
5956
6203
 
5957
6204
  class TextEditorTool {
5958
6205
  editHistory = [];
5959
6206
  confirmationService = ConfirmationService.getInstance();
5960
6207
  async view(filePath, viewRange) {
5961
6208
  try {
5962
- const resolvedPath = path10.resolve(filePath);
5963
- if (await fs11.pathExists(resolvedPath)) {
5964
- const stats = await fs11.stat(resolvedPath);
6209
+ const resolvedPath = path12.resolve(filePath);
6210
+ if (await fs13.pathExists(resolvedPath)) {
6211
+ const stats = await fs13.stat(resolvedPath);
5965
6212
  if (stats.isDirectory()) {
5966
- const files = await fs11.readdir(resolvedPath);
6213
+ const files = await fs13.readdir(resolvedPath);
5967
6214
  return {
5968
6215
  success: true,
5969
6216
  output: `Directory contents of ${filePath}:
@@ -5971,7 +6218,7 @@ ${files.join(`
5971
6218
  `)}`
5972
6219
  };
5973
6220
  }
5974
- const content = await fs11.readFile(resolvedPath, "utf-8");
6221
+ const content = await fs13.readFile(resolvedPath, "utf-8");
5975
6222
  const lines = content.split(`
5976
6223
  `);
5977
6224
  if (viewRange) {
@@ -6011,14 +6258,14 @@ ${numberedLines}${additionalLinesMessage}`
6011
6258
  }
6012
6259
  async strReplace(filePath, oldStr, newStr, replaceAll = false) {
6013
6260
  try {
6014
- const resolvedPath = path10.resolve(filePath);
6015
- if (!await fs11.pathExists(resolvedPath)) {
6261
+ const resolvedPath = path12.resolve(filePath);
6262
+ if (!await fs13.pathExists(resolvedPath)) {
6016
6263
  return {
6017
6264
  success: false,
6018
6265
  error: `File not found: ${filePath}`
6019
6266
  };
6020
6267
  }
6021
- const content = await fs11.readFile(resolvedPath, "utf-8");
6268
+ const content = await fs13.readFile(resolvedPath, "utf-8");
6022
6269
  if (!content.includes(oldStr)) {
6023
6270
  if (oldStr.includes(`
6024
6271
  `)) {
@@ -6086,7 +6333,7 @@ ${numberedLines}${additionalLinesMessage}`
6086
6333
  }
6087
6334
  async create(filePath, content) {
6088
6335
  try {
6089
- const resolvedPath = path10.resolve(filePath);
6336
+ const resolvedPath = path12.resolve(filePath);
6090
6337
  const sessionFlags = this.confirmationService.getSessionFlags();
6091
6338
  if (!sessionFlags.fileOperations && !sessionFlags.allOperations) {
6092
6339
  const contentLines = content.split(`
@@ -6112,8 +6359,8 @@ ${numberedLines}${additionalLinesMessage}`
6112
6359
  };
6113
6360
  }
6114
6361
  }
6115
- const dir = path10.dirname(resolvedPath);
6116
- await fs11.ensureDir(dir);
6362
+ const dir = path12.dirname(resolvedPath);
6363
+ await fs13.ensureDir(dir);
6117
6364
  await writeFilePromise(resolvedPath, content, "utf-8");
6118
6365
  this.editHistory.push({
6119
6366
  command: "create",
@@ -6137,14 +6384,14 @@ ${numberedLines}${additionalLinesMessage}`
6137
6384
  }
6138
6385
  async replaceLines(filePath, startLine, endLine, newContent) {
6139
6386
  try {
6140
- const resolvedPath = path10.resolve(filePath);
6141
- if (!await fs11.pathExists(resolvedPath)) {
6387
+ const resolvedPath = path12.resolve(filePath);
6388
+ if (!await fs13.pathExists(resolvedPath)) {
6142
6389
  return {
6143
6390
  success: false,
6144
6391
  error: `File not found: ${filePath}`
6145
6392
  };
6146
6393
  }
6147
- const fileContent = await fs11.readFile(resolvedPath, "utf-8");
6394
+ const fileContent = await fs13.readFile(resolvedPath, "utf-8");
6148
6395
  const lines = fileContent.split(`
6149
6396
  `);
6150
6397
  if (startLine < 1 || startLine > lines.length) {
@@ -6207,14 +6454,14 @@ ${numberedLines}${additionalLinesMessage}`
6207
6454
  }
6208
6455
  async insert(filePath, insertLine, content) {
6209
6456
  try {
6210
- const resolvedPath = path10.resolve(filePath);
6211
- if (!await fs11.pathExists(resolvedPath)) {
6457
+ const resolvedPath = path12.resolve(filePath);
6458
+ if (!await fs13.pathExists(resolvedPath)) {
6212
6459
  return {
6213
6460
  success: false,
6214
6461
  error: `File not found: ${filePath}`
6215
6462
  };
6216
6463
  }
6217
- const fileContent = await fs11.readFile(resolvedPath, "utf-8");
6464
+ const fileContent = await fs13.readFile(resolvedPath, "utf-8");
6218
6465
  const lines = fileContent.split(`
6219
6466
  `);
6220
6467
  lines.splice(insertLine - 1, 0, content);
@@ -6250,19 +6497,19 @@ ${numberedLines}${additionalLinesMessage}`
6250
6497
  switch (lastEdit.command) {
6251
6498
  case "str_replace":
6252
6499
  if (lastEdit.path && lastEdit.old_str && lastEdit.new_str) {
6253
- const content = await fs11.readFile(lastEdit.path, "utf-8");
6500
+ const content = await fs13.readFile(lastEdit.path, "utf-8");
6254
6501
  const revertedContent = content.replace(lastEdit.new_str, lastEdit.old_str);
6255
6502
  await writeFilePromise(lastEdit.path, revertedContent, "utf-8");
6256
6503
  }
6257
6504
  break;
6258
6505
  case "create":
6259
6506
  if (lastEdit.path) {
6260
- await fs11.remove(lastEdit.path);
6507
+ await fs13.remove(lastEdit.path);
6261
6508
  }
6262
6509
  break;
6263
6510
  case "insert":
6264
6511
  if (lastEdit.path && lastEdit.insert_line) {
6265
- const content = await fs11.readFile(lastEdit.path, "utf-8");
6512
+ const content = await fs13.readFile(lastEdit.path, "utf-8");
6266
6513
  const lines = content.split(`
6267
6514
  `);
6268
6515
  lines.splice(lastEdit.insert_line - 1, 1);
@@ -6707,19 +6954,19 @@ class OpenAICompatibleProvider {
6707
6954
  }
6708
6955
 
6709
6956
  // src/utils/custom-instructions.ts
6710
- import * as path11 from "path";
6711
- import * as os2 from "os";
6712
- import * as fs12 from "fs";
6957
+ import * as path13 from "path";
6958
+ import * as os3 from "os";
6959
+ import * as fs14 from "fs";
6713
6960
  function loadCustomInstructions(workingDirectory = process.cwd()) {
6714
6961
  try {
6715
- let instructionsPath = path11.join(workingDirectory, ".super-agent", "SUPER_AGENT.md");
6716
- if (fs12.existsSync(instructionsPath)) {
6717
- const customInstructions = fs12.readFileSync(instructionsPath, "utf-8");
6962
+ let instructionsPath = path13.join(workingDirectory, ".super-agent", "SUPER_AGENT.md");
6963
+ if (fs14.existsSync(instructionsPath)) {
6964
+ const customInstructions = fs14.readFileSync(instructionsPath, "utf-8");
6718
6965
  return customInstructions.trim();
6719
6966
  }
6720
- instructionsPath = path11.join(os2.homedir(), ".super-agent", "SUPER_AGENT.md");
6721
- if (fs12.existsSync(instructionsPath)) {
6722
- const customInstructions = fs12.readFileSync(instructionsPath, "utf-8");
6967
+ instructionsPath = path13.join(os3.homedir(), ".super-agent", "SUPER_AGENT.md");
6968
+ if (fs14.existsSync(instructionsPath)) {
6969
+ const customInstructions = fs14.readFileSync(instructionsPath, "utf-8");
6723
6970
  return customInstructions.trim();
6724
6971
  }
6725
6972
  return null;
@@ -8422,39 +8669,852 @@ function ChatInterface({
8422
8669
  }, undefined, false, undefined, this);
8423
8670
  }
8424
8671
 
8672
+ // src/commands/web.ts
8673
+ init_settings_manager();
8674
+
8675
+ // src/web/server.ts
8676
+ import { createServer } from "http";
8677
+ import { WebSocketServer } from "ws";
8678
+ import * as fs17 from "fs-extra";
8679
+ import * as path16 from "path";
8680
+ import open from "open";
8681
+ import mime from "mime";
8682
+ var __dirname = "/home/runner/work/super-agent-cli/super-agent-cli/src/web";
8683
+
8684
+ class WebServer {
8685
+ httpServer;
8686
+ wss;
8687
+ agent;
8688
+ hostname;
8689
+ port;
8690
+ clients = new Set;
8691
+ constructor(options) {
8692
+ this.hostname = options.hostname || "localhost";
8693
+ this.port = options.port || 3000;
8694
+ this.agent = options.agent;
8695
+ this.httpServer = createServer((req, res) => {
8696
+ this.handleHttpRequest(req, res);
8697
+ });
8698
+ this.wss = new WebSocketServer({ server: this.httpServer });
8699
+ this.wss.on("connection", (ws) => {
8700
+ this.handleWebSocketConnection(ws);
8701
+ });
8702
+ }
8703
+ async handleHttpRequest(req, res) {
8704
+ const url = req.url || "/";
8705
+ const requestedPath = url === "/" ? "index.html" : url;
8706
+ const sanitizedPath = requestedPath.split("?")[0].split("#")[0];
8707
+ const clientDir = path16.join(__dirname, "../web/client");
8708
+ const absolutePath = path16.resolve(clientDir, sanitizedPath.substring(1));
8709
+ if (!absolutePath.startsWith(clientDir)) {
8710
+ res.writeHead(403, { "Content-Type": "text/plain" });
8711
+ res.end("Forbidden");
8712
+ return;
8713
+ }
8714
+ try {
8715
+ if (await fs17.pathExists(absolutePath)) {
8716
+ const stat5 = await fs17.stat(absolutePath);
8717
+ let filePath = absolutePath;
8718
+ if (stat5.isDirectory()) {
8719
+ filePath = path16.join(absolutePath, "index.html");
8720
+ }
8721
+ const content = await fs17.readFile(filePath);
8722
+ const mimeType = mime.getType(filePath) || "application/octet-stream";
8723
+ res.writeHead(200, { "Content-Type": mimeType });
8724
+ res.end(content);
8725
+ } else {
8726
+ res.writeHead(404);
8727
+ res.end("Not Found");
8728
+ }
8729
+ } catch (error) {
8730
+ console.error("Error serving file:", error);
8731
+ res.writeHead(500);
8732
+ res.end("Internal Server Error");
8733
+ }
8734
+ }
8735
+ handleWebSocketConnection(ws) {
8736
+ this.clients.add(ws);
8737
+ console.log(`\uD83D\uDCE1 Web client connected (${this.clients.size} total)`);
8738
+ this.checkAndSendUpdateNotification(ws);
8739
+ ws.on("message", async (data) => {
8740
+ try {
8741
+ const message = JSON.parse(data.toString());
8742
+ if (message.type === "prompt") {
8743
+ await this.handlePrompt(message.content, ws);
8744
+ } else if (message.type === "get_file_tree") {
8745
+ await this.handleGetFileTree(ws);
8746
+ } else if (message.type === "get_file_content") {
8747
+ await this.handleGetFileContent(message.path, ws);
8748
+ } else if (message.type === "list_sessions") {
8749
+ await this.handleListSessions(ws);
8750
+ } else if (message.type === "switch_session") {
8751
+ await this.handleSwitchSession(message.sessionId, ws);
8752
+ }
8753
+ } catch (error) {
8754
+ console.error("WebSocket message error:", error);
8755
+ ws.send(JSON.stringify({ type: "error", content: "Invalid message format" }));
8756
+ }
8757
+ });
8758
+ ws.on("close", () => {
8759
+ this.clients.delete(ws);
8760
+ console.log(`\uD83D\uDCE1 Web client disconnected (${this.clients.size} remaining)`);
8761
+ });
8762
+ ws.on("error", (error) => {
8763
+ console.error("WebSocket error:", error);
8764
+ });
8765
+ }
8766
+ async handlePrompt(prompt, ws) {
8767
+ try {
8768
+ ws.send(JSON.stringify({ type: "user_message", content: prompt }));
8769
+ const entries = await this.agent.processUserMessage(prompt);
8770
+ for (const entry of entries) {
8771
+ if (entry.type === "assistant") {
8772
+ ws.send(JSON.stringify({
8773
+ type: "assistant_message",
8774
+ content: entry.content
8775
+ }));
8776
+ } else if (entry.type === "tool_call") {
8777
+ ws.send(JSON.stringify({
8778
+ type: "tool_call",
8779
+ tool: entry.toolCall?.function.name,
8780
+ content: "Executing..."
8781
+ }));
8782
+ } else if (entry.type === "tool_result") {
8783
+ ws.send(JSON.stringify({
8784
+ type: "tool_result",
8785
+ tool: entry.toolCall?.function.name,
8786
+ content: entry.content
8787
+ }));
8788
+ }
8789
+ }
8790
+ ws.send(JSON.stringify({ type: "done" }));
8791
+ } catch (error) {
8792
+ ws.send(JSON.stringify({
8793
+ type: "error",
8794
+ content: error.message
8795
+ }));
8796
+ }
8797
+ }
8798
+ async handleGetFileTree(ws) {
8799
+ try {
8800
+ const { getFileIndexer: getFileIndexer2 } = await Promise.resolve().then(() => (init_indexer(), exports_indexer));
8801
+ const indexer = getFileIndexer2();
8802
+ const index = indexer.getIndex();
8803
+ if (!index) {
8804
+ ws.send(JSON.stringify({ type: "file_tree", tree: [] }));
8805
+ return;
8806
+ }
8807
+ const tree = index.entries.filter((e) => !e.path.includes("node_modules") && !e.path.startsWith(".")).map((e) => ({
8808
+ path: e.path,
8809
+ name: path16.basename(e.path),
8810
+ isDirectory: e.isDirectory,
8811
+ size: e.size
8812
+ })).slice(0, 500);
8813
+ ws.send(JSON.stringify({ type: "file_tree", tree }));
8814
+ } catch (error) {
8815
+ ws.send(JSON.stringify({ type: "error", content: error.message }));
8816
+ }
8817
+ }
8818
+ async handleGetFileContent(filePath, ws) {
8819
+ try {
8820
+ const fullPath = path16.join(process.cwd(), filePath);
8821
+ if (!fullPath.startsWith(process.cwd())) {
8822
+ throw new Error("Access denied");
8823
+ }
8824
+ const content = await fs17.readFile(fullPath, "utf-8");
8825
+ ws.send(JSON.stringify({
8826
+ type: "file_content",
8827
+ path: filePath,
8828
+ content: content.slice(0, 1e4)
8829
+ }));
8830
+ } catch (error) {
8831
+ ws.send(JSON.stringify({ type: "error", content: error.message }));
8832
+ }
8833
+ }
8834
+ async handleListSessions(ws) {
8835
+ try {
8836
+ const { getSessionManager: getSessionManager2 } = await Promise.resolve().then(() => (init_session_manager(), exports_session_manager));
8837
+ const sessionManager = getSessionManager2();
8838
+ const sessions = await sessionManager.listSessions();
8839
+ ws.send(JSON.stringify({
8840
+ type: "sessions_list",
8841
+ sessions: sessions.map((s) => ({
8842
+ id: s.id,
8843
+ name: s.name,
8844
+ workingDirectory: s.workingDirectory,
8845
+ messageCount: s.messages.length,
8846
+ lastAccessed: s.lastAccessed
8847
+ }))
8848
+ }));
8849
+ } catch (error) {
8850
+ ws.send(JSON.stringify({ type: "error", content: error.message }));
8851
+ }
8852
+ }
8853
+ async handleSwitchSession(sessionId, ws) {
8854
+ try {
8855
+ const { getSessionManager: getSessionManager2 } = await Promise.resolve().then(() => (init_session_manager(), exports_session_manager));
8856
+ const sessionManager = getSessionManager2();
8857
+ const session = await sessionManager.switchSession(sessionId);
8858
+ if (session) {
8859
+ ws.send(JSON.stringify({
8860
+ type: "session_switched",
8861
+ session: {
8862
+ id: session.id,
8863
+ name: session.name,
8864
+ workingDirectory: session.workingDirectory,
8865
+ messages: session.messages
8866
+ }
8867
+ }));
8868
+ } else {
8869
+ throw new Error("Session not found");
8870
+ }
8871
+ } catch (error) {
8872
+ ws.send(JSON.stringify({ type: "error", content: error.message }));
8873
+ }
8874
+ }
8875
+ async checkAndSendUpdateNotification(ws) {
8876
+ try {
8877
+ const pkg = await Promise.resolve().then(() => __toESM(require_package(), 1));
8878
+ const { getUpdateChecker: getUpdateChecker2 } = await Promise.resolve().then(() => (init_update_checker(), exports_update_checker));
8879
+ const updateChecker = getUpdateChecker2(pkg.version);
8880
+ const updateInfo = await updateChecker.checkForUpdates();
8881
+ if (updateInfo?.updateAvailable) {
8882
+ ws.send(JSON.stringify({
8883
+ type: "update_available",
8884
+ currentVersion: updateInfo.currentVersion,
8885
+ latestVersion: updateInfo.latestVersion
8886
+ }));
8887
+ }
8888
+ } catch (error) {}
8889
+ }
8890
+ async start() {
8891
+ return new Promise((resolve5, reject) => {
8892
+ this.httpServer.listen(this.port, this.hostname, () => {
8893
+ const url = `http://${this.hostname}:${this.port}`;
8894
+ console.log(`\uD83C\uDF10 Web interface available at ${url}`);
8895
+ resolve5();
8896
+ });
8897
+ this.httpServer.on("error", (error) => {
8898
+ reject(error);
8899
+ });
8900
+ });
8901
+ }
8902
+ async openBrowser() {
8903
+ const url = `http://${this.hostname}:${this.port}`;
8904
+ try {
8905
+ await open(url);
8906
+ console.log(`\uD83D\uDE80 Opened browser at ${url}`);
8907
+ } catch (error) {
8908
+ console.warn(`Could not open browser automatically. Please visit ${url}`);
8909
+ }
8910
+ }
8911
+ stop() {
8912
+ this.clients.forEach((client) => {
8913
+ client.close();
8914
+ });
8915
+ this.wss.close();
8916
+ this.httpServer.close();
8917
+ console.log("\uD83D\uDED1 Web server stopped");
8918
+ }
8919
+ }
8920
+
8921
+ // src/commands/web.ts
8922
+ import { Command } from "commander";
8923
+ import chalk from "chalk";
8924
+ function createWebCommand() {
8925
+ 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) => {
8926
+ const port = parseInt(options.port);
8927
+ const settingsManager = getSettingsManager();
8928
+ const apiKey = settingsManager.getApiKey();
8929
+ const baseURL = settingsManager.getBaseURL() || "https://api.openai.com/v1";
8930
+ const model = settingsManager.getCurrentModel();
8931
+ if (!apiKey) {
8932
+ console.error(chalk.red("API Key not found. Please configure it first."));
8933
+ process.exit(1);
8934
+ }
8935
+ console.log(chalk.blue(`Starting web server on port ${port}...`));
8936
+ const agent = new SuperAgent(apiKey, baseURL, model);
8937
+ const server = new WebServer({
8938
+ port,
8939
+ agent,
8940
+ openBrowser: options.browser
8941
+ });
8942
+ try {
8943
+ await server.start();
8944
+ if (options.browser) {
8945
+ await server.openBrowser();
8946
+ }
8947
+ process.on("SIGINT", () => {
8948
+ console.log(chalk.yellow(`
8949
+ Stopping server...`));
8950
+ server.stop();
8951
+ process.exit(0);
8952
+ });
8953
+ } catch (error) {
8954
+ console.error(chalk.red(`Failed to start server: ${error.message}`));
8955
+ process.exit(1);
8956
+ }
8957
+ });
8958
+ return webCommand;
8959
+ }
8960
+ function createServeCommand() {
8961
+ 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) => {
8962
+ console.log(chalk.yellow("Serve mode is currently an alias for 'web' mode with background persistence capabilities."));
8963
+ const port = parseInt(options.port);
8964
+ const settingsManager = getSettingsManager();
8965
+ const apiKey = settingsManager.getApiKey();
8966
+ if (!apiKey) {
8967
+ console.error(chalk.red("API Key not found."));
8968
+ process.exit(1);
8969
+ }
8970
+ const agent = new SuperAgent(apiKey, settingsManager.getBaseURL() || "", settingsManager.getCurrentModel());
8971
+ const server = new WebServer({ port, agent, openBrowser: true });
8972
+ await server.start();
8973
+ await server.openBrowser();
8974
+ });
8975
+ return serveCommand;
8976
+ }
8977
+
8978
+ // src/commands/provider.ts
8979
+ init_settings_manager();
8980
+ import { Command as Command2 } from "commander";
8981
+ import inquirer from "inquirer";
8982
+ import chalk2 from "chalk";
8983
+ function createProviderCommand() {
8984
+ const cmd = new Command2("provider").description("Manage LLM provider configuration");
8985
+ cmd.command("config").description("Interactive provider configuration").action(async () => {
8986
+ const manager = getSettingsManager();
8987
+ const settings = manager.loadUserSettings();
8988
+ const providers = Object.keys(settings.providers);
8989
+ const { selectedProvider } = await inquirer.prompt([
8990
+ {
8991
+ type: "list",
8992
+ name: "selectedProvider",
8993
+ message: "Select a provider to configure:",
8994
+ choices: providers,
8995
+ default: settings.active_provider
8996
+ }
8997
+ ]);
8998
+ const currentConfig = settings.providers[selectedProvider];
8999
+ if (!currentConfig) {
9000
+ console.error(chalk2.red(`Configuration for ${selectedProvider} not found.`));
9001
+ return;
9002
+ }
9003
+ const models = PROVIDER_MODELS[currentConfig.provider] || [];
9004
+ const { apiKey } = await inquirer.prompt([
9005
+ {
9006
+ type: "password",
9007
+ name: "apiKey",
9008
+ message: `Enter API Key for ${selectedProvider} (leave empty to keep current):`,
9009
+ mask: "*"
9010
+ }
9011
+ ]);
9012
+ let selectedModel = currentConfig.model;
9013
+ if (models.length > 0) {
9014
+ const { model } = await inquirer.prompt([
9015
+ {
9016
+ type: "list",
9017
+ name: "model",
9018
+ message: "Select default model:",
9019
+ choices: [...models, "Custom..."],
9020
+ default: currentConfig.model
9021
+ }
9022
+ ]);
9023
+ selectedModel = model;
9024
+ }
9025
+ if (selectedModel === "Custom..." || models.length === 0) {
9026
+ const { customModel } = await inquirer.prompt([
9027
+ {
9028
+ type: "input",
9029
+ name: "customModel",
9030
+ message: "Enter model ID:",
9031
+ default: currentConfig.model
9032
+ }
9033
+ ]);
9034
+ selectedModel = customModel;
9035
+ }
9036
+ const { baseURL } = await inquirer.prompt([
9037
+ {
9038
+ type: "input",
9039
+ name: "baseURL",
9040
+ message: "Enter Base URL (optional, leave empty for default):",
9041
+ default: currentConfig.base_url
9042
+ }
9043
+ ]);
9044
+ console.log(chalk2.blue(`
9045
+ New Configuration:`));
9046
+ console.log(`Provider: ${chalk2.bold(selectedProvider)}`);
9047
+ console.log(`Model: ${chalk2.bold(selectedModel)}`);
9048
+ console.log(`Base URL: ${baseURL || "Default"}`);
9049
+ const { confirm } = await inquirer.prompt([
9050
+ {
9051
+ type: "confirm",
9052
+ name: "confirm",
9053
+ message: "Save these settings?",
9054
+ default: true
9055
+ }
9056
+ ]);
9057
+ if (confirm) {
9058
+ const newProviders = { ...settings.providers };
9059
+ newProviders[selectedProvider] = {
9060
+ ...currentConfig,
9061
+ model: selectedModel,
9062
+ base_url: baseURL || currentConfig.base_url
9063
+ };
9064
+ if (apiKey) {
9065
+ newProviders[selectedProvider].api_key = apiKey;
9066
+ }
9067
+ if (baseURL !== undefined && baseURL !== currentConfig.base_url) {
9068
+ newProviders[selectedProvider].base_url = baseURL;
9069
+ }
9070
+ manager.updateUserSetting("providers", newProviders);
9071
+ if (settings.active_provider !== selectedProvider) {
9072
+ const { makeActive } = await inquirer.prompt([
9073
+ {
9074
+ type: "confirm",
9075
+ name: "makeActive",
9076
+ message: `Set ${selectedProvider} as active provider?`,
9077
+ default: true
9078
+ }
9079
+ ]);
9080
+ if (makeActive) {
9081
+ manager.updateUserSetting("active_provider", selectedProvider);
9082
+ console.log(chalk2.green(`
9083
+ ✅ Settings saved and ${selectedProvider} is now active.`));
9084
+ } else {
9085
+ console.log(chalk2.green(`
9086
+ ✅ Settings saved.`));
9087
+ }
9088
+ } else {
9089
+ console.log(chalk2.green(`
9090
+ ✅ Settings saved.`));
9091
+ }
9092
+ } else {
9093
+ console.log(chalk2.yellow("Configuration cancelled."));
9094
+ }
9095
+ });
9096
+ return cmd;
9097
+ }
9098
+
9099
+ // src/commands/index-cmd.ts
9100
+ import { Command as Command3 } from "commander";
9101
+ import fs18 from "fs/promises";
9102
+ import ignore from "ignore";
9103
+ import chalk3 from "chalk";
9104
+ import path17 from "path";
9105
+ var DEFAULT_IGNORES = [
9106
+ "node_modules",
9107
+ ".git",
9108
+ "dist",
9109
+ "build",
9110
+ "coverage",
9111
+ ".env",
9112
+ "*.log",
9113
+ ".DS_Store",
9114
+ "Thumbs.db"
9115
+ ];
9116
+ function createIndexCommand() {
9117
+ const indexCommand = new Command3("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) => {
9118
+ try {
9119
+ const rootDir = path17.resolve(directory);
9120
+ const outputFile2 = options.output ? path17.resolve(options.output) : path17.join(rootDir, "index.md");
9121
+ const maxDepth = parseInt(options.depth);
9122
+ console.log(chalk3.blue(`Indexing directory: ${rootDir}`));
9123
+ const ig = ignore().add(DEFAULT_IGNORES);
9124
+ if (options.ignore !== false) {
9125
+ try {
9126
+ const gitignorePath = path17.join(rootDir, ".gitignore");
9127
+ const gitignoreContent = await fs18.readFile(gitignorePath, "utf-8");
9128
+ ig.add(gitignoreContent);
9129
+ } catch (e) {}
9130
+ }
9131
+ let outputContent = `# Directory Index
9132
+
9133
+ Generated for: ${rootDir}
9134
+ Date: ${new Date().toISOString()}
9135
+
9136
+ `;
9137
+ outputContent += "## File Structure\n\n```\n";
9138
+ async function buildTree(currentPath, depth, prefix = "") {
9139
+ if (depth > maxDepth) {
9140
+ return;
9141
+ }
9142
+ const relativePath = path17.relative(rootDir, currentPath);
9143
+ if (relativePath && ig.ignores(relativePath)) {
9144
+ return;
9145
+ }
9146
+ const stats = await fs18.stat(currentPath);
9147
+ const isDir = stats.isDirectory();
9148
+ const name = path17.basename(currentPath);
9149
+ if (isDir) {
9150
+ if (relativePath) {
9151
+ outputContent += `${prefix}${name}/
9152
+ `;
9153
+ }
9154
+ const entries = await fs18.readdir(currentPath, {
9155
+ withFileTypes: true
9156
+ });
9157
+ const sortedEntries = entries.sort((a, b) => {
9158
+ if (a.isDirectory() && !b.isDirectory()) {
9159
+ return -1;
9160
+ }
9161
+ if (!a.isDirectory() && b.isDirectory()) {
9162
+ return 1;
9163
+ }
9164
+ return a.name.localeCompare(b.name);
9165
+ });
9166
+ for (let i = 0;i < sortedEntries.length; i++) {
9167
+ const entry = sortedEntries[i];
9168
+ const isLast = i === sortedEntries.length - 1;
9169
+ const newPrefix = relativePath ? prefix + " " : "";
9170
+ await buildTree(path17.join(currentPath, entry.name), depth + 1, newPrefix);
9171
+ }
9172
+ } else {
9173
+ outputContent += `${prefix}${name}
9174
+ `;
9175
+ }
9176
+ }
9177
+ const files = [];
9178
+ async function walk(dir, currentDepth) {
9179
+ if (currentDepth > maxDepth) {
9180
+ return;
9181
+ }
9182
+ const entries = await fs18.readdir(dir, { withFileTypes: true });
9183
+ for (const entry of entries) {
9184
+ const fullPath = path17.join(dir, entry.name);
9185
+ const relPath = path17.relative(rootDir, fullPath);
9186
+ if (ig.ignores(relPath)) {
9187
+ continue;
9188
+ }
9189
+ if (entry.isDirectory()) {
9190
+ await walk(fullPath, currentDepth + 1);
9191
+ } else {
9192
+ files.push(relPath);
9193
+ }
9194
+ }
9195
+ }
9196
+ await walk(rootDir, 0);
9197
+ console.log(chalk3.blue(`Found ${files.length} files.`));
9198
+ outputContent = `# Project Index: ${path17.basename(rootDir)}
9199
+
9200
+ `;
9201
+ outputContent += `Total Files: ${files.length}
9202
+
9203
+ `;
9204
+ outputContent += `## Files
9205
+
9206
+ `;
9207
+ for (const file of files) {
9208
+ outputContent += `### ${file}
9209
+ `;
9210
+ const stats = await fs18.stat(path17.join(rootDir, file));
9211
+ outputContent += `- Size: ${stats.size} bytes
9212
+ `;
9213
+ outputContent += `- Modified: ${stats.mtime.toISOString()}
9214
+
9215
+ `;
9216
+ }
9217
+ await fs18.writeFile(outputFile2, outputContent);
9218
+ console.log(chalk3.green(`✓ Index generated at: ${outputFile2}`));
9219
+ } catch (error) {
9220
+ console.error(chalk3.red(`Error indexing directory: ${error.message}`));
9221
+ process.exit(1);
9222
+ }
9223
+ });
9224
+ return indexCommand;
9225
+ }
9226
+
9227
+ // src/commands/plugins.ts
9228
+ init_settings_manager();
9229
+ import { Command as Command4 } from "commander";
9230
+ function createPluginsCommand() {
9231
+ const pluginsCommand = new Command4("plugins").description("Manage plugins for Super Agent CLI").argument("[action]", "Action to perform (list, install, uninstall)").argument("[target]", "Plugin name or path");
9232
+ pluginsCommand.command("list").description("List installed plugins").action(() => {
9233
+ const manager = getSettingsManager();
9234
+ const settings = manager.loadUserSettings();
9235
+ const plugins = settings.plugins || [];
9236
+ if (plugins.length === 0) {
9237
+ console.log("No plugins installed.");
9238
+ return;
9239
+ }
9240
+ console.log("Installed plugins:");
9241
+ plugins.forEach((p) => console.log(`- ${p}`));
9242
+ });
9243
+ pluginsCommand.command("install <path>").description("Install a plugin from a path, GitHub URL, or registry").action(async (path18) => {
9244
+ try {
9245
+ const manager = PluginManager.getInstance();
9246
+ console.log(`Installing plugin from: ${path18}...`);
9247
+ const installedPath = await manager.installPlugin(path18);
9248
+ console.log(`✅ Plugin installed successfully: ${installedPath}`);
9249
+ } catch (error) {
9250
+ console.error(`❌ Error installing plugin: ${error.message}`);
9251
+ process.exit(1);
9252
+ }
9253
+ });
9254
+ pluginsCommand.command("uninstall <path>").description("Uninstall a plugin").action(async (path18) => {
9255
+ try {
9256
+ const manager = PluginManager.getInstance();
9257
+ await manager.removePlugin(path18);
9258
+ console.log(`✅ Plugin uninstalled: ${path18}`);
9259
+ } catch (error) {
9260
+ console.error(`❌ Error uninstalling plugin: ${error.message}`);
9261
+ process.exit(1);
9262
+ }
9263
+ });
9264
+ return pluginsCommand;
9265
+ }
9266
+
9267
+ // src/commands/skills.ts
9268
+ init_settings_manager();
9269
+ init_manager2();
9270
+ import { Command as Command5 } from "commander";
9271
+ import inquirer2 from "inquirer";
9272
+ import chalk4 from "chalk";
9273
+ function createSkillsCommand() {
9274
+ const skillsCommand = new Command5("skills").description("Manage AI skills");
9275
+ skillsCommand.command("list").description("List available skills").action(async () => {
9276
+ const manager = SkillsManager.getInstance();
9277
+ const skills = await manager.listSkills();
9278
+ if (skills.length === 0) {
9279
+ console.log("No skills found.");
9280
+ } else {
9281
+ console.log("Available skills:");
9282
+ skills.forEach((skill) => console.log(`- ${skill}`));
9283
+ }
9284
+ });
9285
+ skillsCommand.command("create <name>").description("Create a new skill with AI assistance").option("-d, --description <description>", "Description of the skill").action(async (name, options) => {
9286
+ try {
9287
+ const manager = SkillsManager.getInstance();
9288
+ const settingsManager = getSettingsManager();
9289
+ let description = options.description;
9290
+ if (!description) {
9291
+ const answer = await inquirer2.prompt([
9292
+ {
9293
+ type: "input",
9294
+ name: "description",
9295
+ message: "Describe what this skill should do:"
9296
+ }
9297
+ ]);
9298
+ description = answer.description;
9299
+ }
9300
+ console.log(chalk4.blue(`Generating skill '${name}' based on description: "${description}"...`));
9301
+ const apiKey = settingsManager.getApiKey();
9302
+ const baseURL = settingsManager.getBaseURL();
9303
+ const model = settingsManager.getCurrentModel();
9304
+ if (!apiKey) {
9305
+ console.error(chalk4.red("API Key not found. Please configure it first."));
9306
+ return;
9307
+ }
9308
+ const agent = new SuperAgent(apiKey, baseURL, model);
9309
+ await manager.createSkill(name, description, agent);
9310
+ console.log(chalk4.green(`✓ Skill '${name}' created successfully.`));
9311
+ } catch (error) {
9312
+ console.error(chalk4.red(`Error creating skill: ${error.message}`));
9313
+ }
9314
+ });
9315
+ skillsCommand.command("delete <name>").description("Delete a skill").action(async (name) => {
9316
+ try {
9317
+ const manager = SkillsManager.getInstance();
9318
+ await manager.deleteSkill(name);
9319
+ console.log(chalk4.green(`✓ Skill '${name}' deleted.`));
9320
+ } catch (error) {
9321
+ console.error(chalk4.red(`Error deleting skill: ${error.message}`));
9322
+ }
9323
+ });
9324
+ return skillsCommand;
9325
+ }
9326
+
9327
+ // src/commands/import.ts
9328
+ init_settings_manager();
9329
+ init_file_utils();
9330
+ init_manager2();
9331
+ init_manager();
9332
+ import { Command as Command6 } from "commander";
9333
+ import fs19 from "fs-extra";
9334
+ import chalk5 from "chalk";
9335
+ import path18 from "path";
9336
+ function createImportCommand() {
9337
+ const cmd = new Command6("import").description("Import resources from other AI assistants");
9338
+ cmd.command("agents <source>").description("Import agents from source (gemini, claude, kilo)").action(async (source) => {
9339
+ const sourcePath = resolveSourcePath(source);
9340
+ const agentsDir = path18.join(sourcePath, "agents");
9341
+ if (!await fs19.pathExists(agentsDir)) {
9342
+ console.error(chalk5.red(`Agents directory not found at ${agentsDir}`));
9343
+ return;
9344
+ }
9345
+ const files = await fs19.readdir(agentsDir);
9346
+ const manager = AgentsManager.getInstance();
9347
+ let count = 0;
9348
+ for (const file of files) {
9349
+ if (file.endsWith(".json")) {
9350
+ try {
9351
+ const content = await fs19.readJson(path18.join(agentsDir, file));
9352
+ const agentConfig = {
9353
+ name: content.name || path18.parse(file).name,
9354
+ role: content.role || "Assistant",
9355
+ description: content.description || "Imported agent",
9356
+ model: content.model,
9357
+ tools: content.tools,
9358
+ temperature: content.temperature,
9359
+ systemPrompt: content.systemPrompt || content.system_prompt || content.prompt
9360
+ };
9361
+ await manager.createAgent(agentConfig);
9362
+ console.log(chalk5.green(`Imported agent: ${agentConfig.name}`));
9363
+ count++;
9364
+ } catch (error) {
9365
+ console.warn(chalk5.yellow(`Failed to import ${file}: ${error.message}`));
9366
+ }
9367
+ }
9368
+ }
9369
+ console.log(chalk5.bold(`Imported ${count} agents.`));
9370
+ });
9371
+ cmd.command("skills <source>").description("Import skills from source (gemini, claude, kilo)").action(async (source) => {
9372
+ const sourcePath = resolveSourcePath(source);
9373
+ const skillsDir = path18.join(sourcePath, "skills");
9374
+ if (!await fs19.pathExists(skillsDir)) {
9375
+ console.error(chalk5.red(`Skills directory not found at ${skillsDir}`));
9376
+ return;
9377
+ }
9378
+ const files = await fs19.readdir(skillsDir);
9379
+ const manager = SkillsManager.getInstance();
9380
+ let count = 0;
9381
+ for (const file of files) {
9382
+ if (file.endsWith(".ts") || file.endsWith(".js")) {
9383
+ try {
9384
+ const content = await fs19.readFile(path18.join(skillsDir, file), "utf-8");
9385
+ const name = path18.parse(file).name;
9386
+ await manager.saveSkill(name, content);
9387
+ console.log(chalk5.green(`Imported skill: ${name}`));
9388
+ count++;
9389
+ } catch (error) {
9390
+ console.warn(chalk5.yellow(`Failed to import ${file}: ${error.message}`));
9391
+ }
9392
+ }
9393
+ }
9394
+ console.log(chalk5.bold(`Imported ${count} skills.`));
9395
+ });
9396
+ cmd.command("hooks <source>").description("Import hooks from source settings").action(async (source) => {
9397
+ const sourcePath = resolveSourcePath(source);
9398
+ const settingsFile = source.toLowerCase() === "claude" ? "settings.local.json" : "settings.json";
9399
+ const fullPath = path18.join(sourcePath, settingsFile);
9400
+ if (!await fs19.pathExists(fullPath)) {
9401
+ console.error(chalk5.red(`Settings file not found at ${fullPath}`));
9402
+ return;
9403
+ }
9404
+ try {
9405
+ const settings = await fs19.readJson(fullPath);
9406
+ if (settings.hooks) {
9407
+ const manager = getSettingsManager();
9408
+ const currentHooks = manager.getUserSetting("hooks") || {};
9409
+ const mergedHooks = { ...currentHooks, ...settings.hooks };
9410
+ manager.updateUserSetting("hooks", mergedHooks);
9411
+ console.log(chalk5.green(`Imported ${Object.keys(settings.hooks).length} hooks.`));
9412
+ } else {
9413
+ console.log(chalk5.yellow("No hooks found in settings file."));
9414
+ }
9415
+ } catch (error) {
9416
+ console.error(chalk5.red(`Failed to import hooks: ${error.message}`));
9417
+ }
9418
+ });
9419
+ return cmd;
9420
+ }
9421
+
9422
+ // src/commands/agents.ts
9423
+ init_settings_manager();
9424
+ init_manager();
9425
+ import { Command as Command7 } from "commander";
9426
+ import inquirer3 from "inquirer";
9427
+ import chalk6 from "chalk";
9428
+ function createAgentsCommand() {
9429
+ const agentsCommand = new Command7("agents").description("Manage AI agents");
9430
+ agentsCommand.command("list").description("List available agents").action(async () => {
9431
+ const manager = AgentsManager.getInstance();
9432
+ const agents = await manager.listAgents();
9433
+ if (agents.length === 0) {
9434
+ console.log("No agents found.");
9435
+ } else {
9436
+ console.log("Available agents:");
9437
+ agents.forEach((agent) => {
9438
+ console.log(`- ${chalk6.bold(agent.name)} (${agent.role})`);
9439
+ console.log(` ${chalk6.dim(agent.description)}`);
9440
+ });
9441
+ }
9442
+ });
9443
+ 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) => {
9444
+ try {
9445
+ const manager = AgentsManager.getInstance();
9446
+ const settingsManager = getSettingsManager();
9447
+ let description = options.description;
9448
+ if (!description) {
9449
+ const answer = await inquirer3.prompt([
9450
+ {
9451
+ type: "input",
9452
+ name: "description",
9453
+ message: "Describe the agent's role and purpose:"
9454
+ }
9455
+ ]);
9456
+ description = answer.description;
9457
+ }
9458
+ console.log(chalk6.blue(`Generating agent configuration for '${name}'...`));
9459
+ const apiKey = settingsManager.getApiKey();
9460
+ const baseURL = settingsManager.getBaseURL();
9461
+ const model = settingsManager.getCurrentModel();
9462
+ if (!apiKey) {
9463
+ console.error(chalk6.red("API Key not found. Please configure it first."));
9464
+ return;
9465
+ }
9466
+ const agent = new SuperAgent(apiKey, baseURL, model);
9467
+ await manager.generateAgent(name, description, agent);
9468
+ console.log(chalk6.green(`✓ Agent '${name}' created successfully.`));
9469
+ } catch (error) {
9470
+ console.error(chalk6.red(`Error creating agent: ${error.message}`));
9471
+ }
9472
+ });
9473
+ agentsCommand.command("delete <name>").description("Delete an agent").action(async (name) => {
9474
+ try {
9475
+ const manager = AgentsManager.getInstance();
9476
+ await manager.deleteAgent(name);
9477
+ console.log(chalk6.green(`✓ Agent '${name}' deleted.`));
9478
+ } catch (error) {
9479
+ console.error(chalk6.red(`Error deleting agent: ${error.message}`));
9480
+ }
9481
+ });
9482
+ return agentsCommand;
9483
+ }
9484
+
8425
9485
  // src/commands/mcp.ts
8426
9486
  init_config();
8427
- import { Command } from "commander";
8428
- import chalk from "chalk";
9487
+ import { Command as Command8 } from "commander";
9488
+ import chalk7 from "chalk";
8429
9489
  function createMCPCommand() {
8430
- const mcpCommand = new Command("mcp");
9490
+ const mcpCommand = new Command8("mcp");
8431
9491
  mcpCommand.description("Manage MCP (Model Context Protocol) servers");
8432
9492
  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
9493
  try {
8434
9494
  if (PREDEFINED_SERVERS[name]) {
8435
9495
  const config2 = PREDEFINED_SERVERS[name];
8436
9496
  addMCPServer(config2);
8437
- console.log(chalk.green(`✓ Added predefined MCP server: ${name}`));
9497
+ console.log(chalk7.green(`✓ Added predefined MCP server: ${name}`));
8438
9498
  const manager2 = getMCPManager();
8439
9499
  await manager2.addServer(config2);
8440
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
9500
+ console.log(chalk7.green(`✓ Connected to MCP server: ${name}`));
8441
9501
  const tools2 = manager2.getTools().filter((t) => t.serverName === name);
8442
- console.log(chalk.blue(` Available tools: ${tools2.length}`));
9502
+ console.log(chalk7.blue(` Available tools: ${tools2.length}`));
8443
9503
  return;
8444
9504
  }
8445
9505
  const transportType = options.transport.toLowerCase();
8446
9506
  if (transportType === "stdio") {
8447
9507
  if (!options.command) {
8448
- console.error(chalk.red("Error: --command is required for stdio transport"));
9508
+ console.error(chalk7.red("Error: --command is required for stdio transport"));
8449
9509
  process.exit(1);
8450
9510
  }
8451
9511
  } else if (transportType === "http" || transportType === "sse" || transportType === "streamable_http") {
8452
9512
  if (!options.url) {
8453
- console.error(chalk.red(`Error: --url is required for ${transportType} transport`));
9513
+ console.error(chalk7.red(`Error: --url is required for ${transportType} transport`));
8454
9514
  process.exit(1);
8455
9515
  }
8456
9516
  } else {
8457
- console.error(chalk.red("Error: Transport type must be stdio, http, sse, or streamable_http"));
9517
+ console.error(chalk7.red("Error: Transport type must be stdio, http, sse, or streamable_http"));
8458
9518
  process.exit(1);
8459
9519
  }
8460
9520
  const env = {};
@@ -8483,14 +9543,14 @@ function createMCPCommand() {
8483
9543
  }
8484
9544
  };
8485
9545
  addMCPServer(config);
8486
- console.log(chalk.green(`✓ Added MCP server: ${name}`));
9546
+ console.log(chalk7.green(`✓ Added MCP server: ${name}`));
8487
9547
  const manager = getMCPManager();
8488
9548
  await manager.addServer(config);
8489
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
9549
+ console.log(chalk7.green(`✓ Connected to MCP server: ${name}`));
8490
9550
  const tools = manager.getTools().filter((t) => t.serverName === name);
8491
- console.log(chalk.blue(` Available tools: ${tools.length}`));
9551
+ console.log(chalk7.blue(` Available tools: ${tools.length}`));
8492
9552
  } catch (error) {
8493
- console.error(chalk.red(`Error adding MCP server: ${error.message}`));
9553
+ console.error(chalk7.red(`Error adding MCP server: ${error.message}`));
8494
9554
  process.exit(1);
8495
9555
  }
8496
9556
  });
@@ -8500,7 +9560,7 @@ function createMCPCommand() {
8500
9560
  try {
8501
9561
  config = JSON.parse(jsonConfig);
8502
9562
  } catch (error) {
8503
- console.error(chalk.red("Error: Invalid JSON configuration"));
9563
+ console.error(chalk7.red("Error: Invalid JSON configuration"));
8504
9564
  process.exit(1);
8505
9565
  }
8506
9566
  const serverConfig = {
@@ -8525,14 +9585,14 @@ function createMCPCommand() {
8525
9585
  }
8526
9586
  }
8527
9587
  addMCPServer(serverConfig);
8528
- console.log(chalk.green(`✓ Added MCP server: ${name}`));
9588
+ console.log(chalk7.green(`✓ Added MCP server: ${name}`));
8529
9589
  const manager = getMCPManager();
8530
9590
  await manager.addServer(serverConfig);
8531
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
9591
+ console.log(chalk7.green(`✓ Connected to MCP server: ${name}`));
8532
9592
  const tools = manager.getTools().filter((t) => t.serverName === name);
8533
- console.log(chalk.blue(` Available tools: ${tools.length}`));
9593
+ console.log(chalk7.blue(` Available tools: ${tools.length}`));
8534
9594
  } catch (error) {
8535
- console.error(chalk.red(`Error adding MCP server: ${error.message}`));
9595
+ console.error(chalk7.red(`Error adding MCP server: ${error.message}`));
8536
9596
  process.exit(1);
8537
9597
  }
8538
9598
  });
@@ -8541,9 +9601,9 @@ function createMCPCommand() {
8541
9601
  const manager = getMCPManager();
8542
9602
  await manager.removeServer(name);
8543
9603
  removeMCPServer(name);
8544
- console.log(chalk.green(`✓ Removed MCP server: ${name}`));
9604
+ console.log(chalk7.green(`✓ Removed MCP server: ${name}`));
8545
9605
  } catch (error) {
8546
- console.error(chalk.red(`Error removing MCP server: ${error.message}`));
9606
+ console.error(chalk7.red(`Error removing MCP server: ${error.message}`));
8547
9607
  process.exit(1);
8548
9608
  }
8549
9609
  });
@@ -8551,15 +9611,15 @@ function createMCPCommand() {
8551
9611
  const config = loadMCPConfig();
8552
9612
  const manager = getMCPManager();
8553
9613
  if (config.servers.length === 0) {
8554
- console.log(chalk.yellow("No MCP servers configured"));
9614
+ console.log(chalk7.yellow("No MCP servers configured"));
8555
9615
  return;
8556
9616
  }
8557
- console.log(chalk.bold("Configured MCP servers:"));
9617
+ console.log(chalk7.bold("Configured MCP servers:"));
8558
9618
  console.log();
8559
9619
  for (const server of config.servers) {
8560
9620
  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}`);
9621
+ const status = isConnected ? chalk7.green("✓ Connected") : chalk7.red("✗ Disconnected");
9622
+ console.log(`${chalk7.bold(server.name)}: ${status}`);
8563
9623
  if (server.transport) {
8564
9624
  console.log(` Transport: ${server.transport.type}`);
8565
9625
  if (server.transport.type === "stdio") {
@@ -8592,15 +9652,15 @@ function createMCPCommand() {
8592
9652
  const config = loadMCPConfig();
8593
9653
  const serverConfig = config.servers.find((s) => s.name === name);
8594
9654
  if (!serverConfig) {
8595
- console.error(chalk.red(`Server ${name} not found`));
9655
+ console.error(chalk7.red(`Server ${name} not found`));
8596
9656
  process.exit(1);
8597
9657
  }
8598
- console.log(chalk.blue(`Testing connection to ${name}...`));
9658
+ console.log(chalk7.blue(`Testing connection to ${name}...`));
8599
9659
  const manager = getMCPManager();
8600
9660
  await manager.addServer(serverConfig);
8601
9661
  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}`));
9662
+ console.log(chalk7.green(`✓ Successfully connected to ${name}`));
9663
+ console.log(chalk7.blue(` Available tools: ${tools.length}`));
8604
9664
  if (tools.length > 0) {
8605
9665
  console.log(" Tools:");
8606
9666
  tools.forEach((tool) => {
@@ -8609,82 +9669,44 @@ function createMCPCommand() {
8609
9669
  });
8610
9670
  }
8611
9671
  } catch (error) {
8612
- console.error(chalk.red(`✗ Failed to connect to ${name}: ${error.message}`));
9672
+ console.error(chalk7.red(`✗ Failed to connect to ${name}: ${error.message}`));
8613
9673
  process.exit(1);
8614
9674
  }
8615
9675
  });
8616
9676
  return mcpCommand;
8617
9677
  }
8618
9678
 
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() {
9679
+ // src/commands/git.ts
9680
+ init_settings_manager();
9681
+ import { Command as Command9 } from "commander";
9682
+ async function loadApiKey() {
8651
9683
  const manager = getSettingsManager();
8652
9684
  return manager.getApiKey();
8653
9685
  }
8654
- function loadBaseURL() {
9686
+ async function loadBaseURL() {
8655
9687
  const manager = getSettingsManager();
8656
9688
  return manager.getBaseURL();
8657
9689
  }
9690
+ async function loadModel() {
9691
+ const manager = getSettingsManager();
9692
+ return process.env.SUPER_AGENT_MODEL || manager.getCurrentModel();
9693
+ }
8658
9694
  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
- }
9695
+ if (!apiKey && !baseURL) {
9696
+ return;
9697
+ }
9698
+ const manager = getSettingsManager();
9699
+ const settings = manager.loadUserSettings();
9700
+ const activeProviderId = settings.active_provider;
9701
+ if (settings.providers[activeProviderId]) {
8666
9702
  if (apiKey) {
8667
9703
  settings.providers[activeProviderId].api_key = apiKey;
8668
- console.log(`✅ API key saved for provider '${activeProviderId}' to ~/.super-agent/settings.json`);
8669
9704
  }
8670
9705
  if (baseURL) {
8671
9706
  settings.providers[activeProviderId].base_url = baseURL;
8672
- console.log(`✅ Base URL saved for provider '${activeProviderId}' to ~/.super-agent/settings.json`);
8673
9707
  }
8674
9708
  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
9709
  }
8687
- return model;
8688
9710
  }
8689
9711
  async function handleCommitAndPushHeadless(apiKey, baseURL, model, maxToolRounds) {
8690
9712
  try {
@@ -8759,6 +9781,122 @@ Respond with ONLY the commit message, no additional text.`;
8759
9781
  process.exit(1);
8760
9782
  }
8761
9783
  }
9784
+ function createGitCommand() {
9785
+ const gitCommand = new Command9("git").description("Git operations with AI assistance");
9786
+ 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) => {
9787
+ if (options.directory) {
9788
+ try {
9789
+ process.chdir(options.directory);
9790
+ } catch (error) {
9791
+ console.error(`Error changing directory to ${options.directory}:`, error.message);
9792
+ process.exit(1);
9793
+ }
9794
+ }
9795
+ try {
9796
+ const apiKey = options.apiKey || await loadApiKey();
9797
+ const baseURL = options.baseUrl || await loadBaseURL();
9798
+ const model = options.model || await loadModel();
9799
+ const maxToolRounds = parseInt(options.maxToolRounds) || 400;
9800
+ if (!apiKey) {
9801
+ console.error("❌ Error: API key required for git operations. Set SUPER_AGENT_API_KEY environment variable.");
9802
+ process.exit(1);
9803
+ }
9804
+ if (options.apiKey || options.baseUrl) {
9805
+ await saveCommandLineSettings(options.apiKey, options.baseUrl);
9806
+ }
9807
+ await handleCommitAndPushHeadless(apiKey, baseURL, model, maxToolRounds);
9808
+ } catch (error) {
9809
+ console.error("❌ Error during git commit-and-push:", error.message);
9810
+ process.exit(1);
9811
+ }
9812
+ });
9813
+ return gitCommand;
9814
+ }
9815
+
9816
+ // src/commands/index.ts
9817
+ function registerCommands(program) {
9818
+ program.addCommand(createMCPCommand());
9819
+ program.addCommand(createPluginsCommand());
9820
+ program.addCommand(createGitCommand());
9821
+ program.addCommand(createWebCommand());
9822
+ program.addCommand(createServeCommand());
9823
+ program.addCommand(createSkillsCommand());
9824
+ program.addCommand(createAgentsCommand());
9825
+ program.addCommand(createImportCommand());
9826
+ program.addCommand(createProviderCommand());
9827
+ program.addCommand(createIndexCommand());
9828
+ }
9829
+
9830
+ // src/index.ts
9831
+ var import__package = __toESM(require_package(), 1);
9832
+ import { program } from "commander";
9833
+ import * as dotenv from "dotenv";
9834
+ import { render } from "ink";
9835
+ import React4 from "react";
9836
+ dotenv.config();
9837
+ process.on("SIGTERM", () => {
9838
+ if (process.stdin.isTTY && process.stdin.setRawMode) {
9839
+ try {
9840
+ process.stdin.setRawMode(false);
9841
+ } catch (e) {}
9842
+ }
9843
+ console.log(`
9844
+ Gracefully shutting down...`);
9845
+ process.exit(0);
9846
+ });
9847
+ process.on("uncaughtException", (error) => {
9848
+ console.error("Uncaught exception:", error);
9849
+ process.exit(1);
9850
+ });
9851
+ process.on("unhandledRejection", (reason, promise) => {
9852
+ console.error("Unhandled rejection at:", promise, "reason:", reason);
9853
+ process.exit(1);
9854
+ });
9855
+ function ensureUserSettingsDirectory() {
9856
+ try {
9857
+ const manager = getSettingsManager();
9858
+ manager.loadUserSettings();
9859
+ } catch (error) {}
9860
+ }
9861
+ function loadApiKey2() {
9862
+ const manager = getSettingsManager();
9863
+ return manager.getApiKey();
9864
+ }
9865
+ function loadBaseURL2() {
9866
+ const manager = getSettingsManager();
9867
+ return manager.getBaseURL();
9868
+ }
9869
+ async function saveCommandLineSettings2(apiKey, baseURL) {
9870
+ try {
9871
+ const manager = getSettingsManager();
9872
+ const settings = manager.loadUserSettings();
9873
+ const activeProviderId = settings.active_provider;
9874
+ if (!settings.providers[activeProviderId]) {
9875
+ return;
9876
+ }
9877
+ if (apiKey) {
9878
+ settings.providers[activeProviderId].api_key = apiKey;
9879
+ console.log(`✅ API key saved for provider '${activeProviderId}' to ~/.super-agent/settings.json`);
9880
+ }
9881
+ if (baseURL) {
9882
+ settings.providers[activeProviderId].base_url = baseURL;
9883
+ console.log(`✅ Base URL saved for provider '${activeProviderId}' to ~/.super-agent/settings.json`);
9884
+ }
9885
+ manager.saveUserSettings(settings);
9886
+ } catch (error) {
9887
+ console.warn("⚠️ Could not save settings to file:", error instanceof Error ? error.message : "Unknown error");
9888
+ }
9889
+ }
9890
+ function loadModel2() {
9891
+ let model = process.env.SUPER_AGENT_MODEL;
9892
+ if (!model) {
9893
+ try {
9894
+ const manager = getSettingsManager();
9895
+ model = manager.getCurrentModel();
9896
+ } catch (error) {}
9897
+ }
9898
+ return model;
9899
+ }
8762
9900
  async function processPromptHeadless(prompt, apiKey, baseURL, model, maxToolRounds) {
8763
9901
  try {
8764
9902
  const agent = new SuperAgent(apiKey, baseURL, model, maxToolRounds);
@@ -8823,9 +9961,9 @@ program.name("super-agent").description("A conversational AI CLI tool powered by
8823
9961
  }
8824
9962
  }
8825
9963
  try {
8826
- const apiKey = options.apiKey || loadApiKey();
8827
- const baseURL = options.baseUrl || loadBaseURL();
8828
- const model = options.model || loadModel();
9964
+ const apiKey = options.apiKey || loadApiKey2();
9965
+ const baseURL = options.baseUrl || loadBaseURL2();
9966
+ const model = options.model || loadModel2();
8829
9967
  const maxToolRounds = parseInt(options.maxToolRounds) || 400;
8830
9968
  if (!apiKey && !options.prompt) {
8831
9969
  console.warn("⚠️ Warning: No API key found. Some features may not work. Use /config or set SUPER_AGENT_API_KEY.");
@@ -8834,7 +9972,7 @@ program.name("super-agent").description("A conversational AI CLI tool powered by
8834
9972
  process.exit(1);
8835
9973
  }
8836
9974
  if (options.apiKey || options.baseUrl) {
8837
- await saveCommandLineSettings(options.apiKey, options.baseUrl);
9975
+ await saveCommandLineSettings2(options.apiKey, options.baseUrl);
8838
9976
  }
8839
9977
  if (options.prompt) {
8840
9978
  await processPromptHeadless(options.prompt, apiKey, baseURL, model, maxToolRounds);
@@ -8862,141 +10000,6 @@ program.name("super-agent").description("A conversational AI CLI tool powered by
8862
10000
  process.exit(1);
8863
10001
  }
8864
10002
  });
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());
10003
+ registerCommands(program);
10004
+ program.parse();
9002
10005
  program.parse();