@involvex/super-agent-cli 0.0.62 → 0.0.64
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 +1165 -471
- package/dist/super-agent-cli.exe +0 -0
- package/package.json +5 -2
- package/tsc_output.txt +0 -2
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
|
-
|
|
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
|
|
422
|
-
import * as
|
|
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 =
|
|
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 (
|
|
444
|
-
const content = await
|
|
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
|
|
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
|
|
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 =
|
|
494
|
-
const relativePath =
|
|
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
|
|
831
|
+
const stats = await fs11.stat(fullPath);
|
|
505
832
|
entries.push({
|
|
506
833
|
path: relativePath,
|
|
507
834
|
size: stats.size,
|
|
@@ -542,8 +869,8 @@ __export(exports_session_manager, {
|
|
|
542
869
|
getSessionManager: () => getSessionManager,
|
|
543
870
|
SessionManager: () => SessionManager
|
|
544
871
|
});
|
|
545
|
-
import * as
|
|
546
|
-
import * as
|
|
872
|
+
import * as fs15 from "fs-extra";
|
|
873
|
+
import * as path14 from "path";
|
|
547
874
|
|
|
548
875
|
class SessionManager {
|
|
549
876
|
static instance;
|
|
@@ -551,8 +878,8 @@ class SessionManager {
|
|
|
551
878
|
currentSession = null;
|
|
552
879
|
constructor() {
|
|
553
880
|
const settingsManager = getSettingsManager();
|
|
554
|
-
this.sessionsDir =
|
|
555
|
-
|
|
881
|
+
this.sessionsDir = path14.join(settingsManager.getStorageDirectory(), "sessions");
|
|
882
|
+
fs15.ensureDirSync(this.sessionsDir);
|
|
556
883
|
}
|
|
557
884
|
static getInstance() {
|
|
558
885
|
if (!SessionManager.instance) {
|
|
@@ -561,18 +888,18 @@ class SessionManager {
|
|
|
561
888
|
return SessionManager.instance;
|
|
562
889
|
}
|
|
563
890
|
generateSessionId(workingDir) {
|
|
564
|
-
const normalized =
|
|
891
|
+
const normalized = path14.normalize(workingDir).toLowerCase();
|
|
565
892
|
return Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
|
|
566
893
|
}
|
|
567
894
|
getSessionFilePath(sessionId) {
|
|
568
|
-
return
|
|
895
|
+
return path14.join(this.sessionsDir, `${sessionId}.json`);
|
|
569
896
|
}
|
|
570
897
|
async getOrCreateSession(workingDirectory, name) {
|
|
571
898
|
const sessionId = this.generateSessionId(workingDirectory);
|
|
572
899
|
const sessionFile = this.getSessionFilePath(sessionId);
|
|
573
900
|
try {
|
|
574
|
-
if (await
|
|
575
|
-
const session = await
|
|
901
|
+
if (await fs15.pathExists(sessionFile)) {
|
|
902
|
+
const session = await fs15.readJson(sessionFile);
|
|
576
903
|
session.lastAccessed = Date.now();
|
|
577
904
|
this.currentSession = session;
|
|
578
905
|
await this.saveSession(session);
|
|
@@ -582,7 +909,7 @@ class SessionManager {
|
|
|
582
909
|
const newSession = {
|
|
583
910
|
id: sessionId,
|
|
584
911
|
workingDirectory,
|
|
585
|
-
name: name ||
|
|
912
|
+
name: name || path14.basename(workingDirectory),
|
|
586
913
|
messages: [],
|
|
587
914
|
lastAccessed: Date.now(),
|
|
588
915
|
createdAt: Date.now()
|
|
@@ -593,7 +920,7 @@ class SessionManager {
|
|
|
593
920
|
}
|
|
594
921
|
async saveSession(session) {
|
|
595
922
|
const sessionFile = this.getSessionFilePath(session.id);
|
|
596
|
-
await
|
|
923
|
+
await fs15.outputJson(sessionFile, session, { spaces: 2 });
|
|
597
924
|
}
|
|
598
925
|
async addMessage(message) {
|
|
599
926
|
if (!this.currentSession) {
|
|
@@ -604,12 +931,12 @@ class SessionManager {
|
|
|
604
931
|
await this.saveSession(this.currentSession);
|
|
605
932
|
}
|
|
606
933
|
async listSessions() {
|
|
607
|
-
const sessionFiles = await
|
|
934
|
+
const sessionFiles = await fs15.readdir(this.sessionsDir);
|
|
608
935
|
const sessions = [];
|
|
609
936
|
for (const file of sessionFiles) {
|
|
610
937
|
if (file.endsWith(".json")) {
|
|
611
938
|
try {
|
|
612
|
-
const session = await
|
|
939
|
+
const session = await fs15.readJson(path14.join(this.sessionsDir, file));
|
|
613
940
|
sessions.push(session);
|
|
614
941
|
} catch (error) {}
|
|
615
942
|
}
|
|
@@ -619,8 +946,8 @@ class SessionManager {
|
|
|
619
946
|
}
|
|
620
947
|
async deleteSession(sessionId) {
|
|
621
948
|
const sessionFile = this.getSessionFilePath(sessionId);
|
|
622
|
-
if (await
|
|
623
|
-
await
|
|
949
|
+
if (await fs15.pathExists(sessionFile)) {
|
|
950
|
+
await fs15.remove(sessionFile);
|
|
624
951
|
}
|
|
625
952
|
}
|
|
626
953
|
getCurrentSession() {
|
|
@@ -629,8 +956,8 @@ class SessionManager {
|
|
|
629
956
|
async switchSession(sessionId) {
|
|
630
957
|
const sessionFile = this.getSessionFilePath(sessionId);
|
|
631
958
|
try {
|
|
632
|
-
if (await
|
|
633
|
-
const session = await
|
|
959
|
+
if (await fs15.pathExists(sessionFile)) {
|
|
960
|
+
const session = await fs15.readJson(sessionFile);
|
|
634
961
|
session.lastAccessed = Date.now();
|
|
635
962
|
this.currentSession = session;
|
|
636
963
|
await this.saveSession(session);
|
|
@@ -651,12 +978,15 @@ var init_session_manager = __esm(() => {
|
|
|
651
978
|
var require_package = __commonJS((exports, module) => {
|
|
652
979
|
module.exports = {
|
|
653
980
|
name: "@involvex/super-agent-cli",
|
|
654
|
-
version: "0.0.
|
|
981
|
+
version: "0.0.64",
|
|
655
982
|
description: "An open-source AI agent that brings the power of Super Agent directly into your terminal.",
|
|
656
983
|
keywords: [
|
|
657
984
|
"cli",
|
|
658
985
|
"agent",
|
|
659
|
-
"
|
|
986
|
+
"cli-agent",
|
|
987
|
+
"ai-cli",
|
|
988
|
+
"coding-cli",
|
|
989
|
+
"ai-coding-cli",
|
|
660
990
|
"ai"
|
|
661
991
|
],
|
|
662
992
|
homepage: "https://involvex.github.io/super-agent-cli/",
|
|
@@ -758,8 +1088,8 @@ __export(exports_update_checker, {
|
|
|
758
1088
|
getUpdateChecker: () => getUpdateChecker,
|
|
759
1089
|
UpdateChecker: () => UpdateChecker
|
|
760
1090
|
});
|
|
761
|
-
import * as
|
|
762
|
-
import * as
|
|
1091
|
+
import * as fs16 from "fs-extra";
|
|
1092
|
+
import * as path15 from "path";
|
|
763
1093
|
import axios3 from "axios";
|
|
764
1094
|
|
|
765
1095
|
class UpdateChecker {
|
|
@@ -768,7 +1098,7 @@ class UpdateChecker {
|
|
|
768
1098
|
currentVersion;
|
|
769
1099
|
constructor(currentVersion) {
|
|
770
1100
|
const settingsManager = getSettingsManager();
|
|
771
|
-
this.cacheFile =
|
|
1101
|
+
this.cacheFile = path15.join(settingsManager.getStorageDirectory(), "update-cache.json");
|
|
772
1102
|
this.currentVersion = currentVersion;
|
|
773
1103
|
}
|
|
774
1104
|
static getInstance(currentVersion) {
|
|
@@ -779,8 +1109,8 @@ class UpdateChecker {
|
|
|
779
1109
|
}
|
|
780
1110
|
async loadCache() {
|
|
781
1111
|
try {
|
|
782
|
-
if (await
|
|
783
|
-
const cache = await
|
|
1112
|
+
if (await fs16.pathExists(this.cacheFile)) {
|
|
1113
|
+
const cache = await fs16.readJson(this.cacheFile);
|
|
784
1114
|
const now = Date.now();
|
|
785
1115
|
if (cache.lastChecked && now - cache.lastChecked < CACHE_DURATION) {
|
|
786
1116
|
return cache;
|
|
@@ -791,7 +1121,7 @@ class UpdateChecker {
|
|
|
791
1121
|
}
|
|
792
1122
|
async saveCache(info) {
|
|
793
1123
|
try {
|
|
794
|
-
await
|
|
1124
|
+
await fs16.outputJson(this.cacheFile, info);
|
|
795
1125
|
} catch (error) {}
|
|
796
1126
|
}
|
|
797
1127
|
compareVersions(v1, v2) {
|
|
@@ -971,91 +1301,30 @@ class ConfirmationService extends EventEmitter {
|
|
|
971
1301
|
}
|
|
972
1302
|
throw new Error("VS Code not found");
|
|
973
1303
|
}
|
|
974
|
-
isPending() {
|
|
975
|
-
return this.pendingConfirmation !== null;
|
|
976
|
-
}
|
|
977
|
-
resetSession() {
|
|
978
|
-
this.sessionFlags = {
|
|
979
|
-
fileOperations: false,
|
|
980
|
-
bashCommands: false,
|
|
981
|
-
allOperations: false
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
getSessionFlags() {
|
|
985
|
-
return { ...this.sessionFlags };
|
|
986
|
-
}
|
|
987
|
-
setSessionFlag(flagType, value) {
|
|
988
|
-
this.sessionFlags[flagType] = value;
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
// src/index.ts
|
|
993
|
-
init_settings_manager();
|
|
994
|
-
|
|
995
|
-
// src/utils/file-utils.ts
|
|
996
|
-
import * as fs2 from "fs-extra";
|
|
997
|
-
import * as path2 from "path";
|
|
998
|
-
async function listFilesRecursive(dir, baseDir = dir, maxDepth = 3) {
|
|
999
|
-
const result = [];
|
|
1000
|
-
try {
|
|
1001
|
-
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
1002
|
-
for (const entry of entries) {
|
|
1003
|
-
const fullPath = path2.join(dir, entry.name);
|
|
1004
|
-
const relativePath = path2.relative(baseDir, fullPath);
|
|
1005
|
-
const isIgnored = [
|
|
1006
|
-
"node_modules",
|
|
1007
|
-
".git",
|
|
1008
|
-
"dist",
|
|
1009
|
-
"build",
|
|
1010
|
-
".next",
|
|
1011
|
-
"target",
|
|
1012
|
-
"vendor"
|
|
1013
|
-
].includes(entry.name);
|
|
1014
|
-
if (isIgnored) {
|
|
1015
|
-
continue;
|
|
1016
|
-
}
|
|
1017
|
-
if (entry.name.startsWith(".") && entry.name !== ".env") {
|
|
1018
|
-
continue;
|
|
1019
|
-
}
|
|
1020
|
-
result.push({
|
|
1021
|
-
name: entry.name,
|
|
1022
|
-
path: relativePath,
|
|
1023
|
-
isDirectory: entry.isDirectory()
|
|
1024
|
-
});
|
|
1025
|
-
if (entry.isDirectory() && maxDepth > 0) {
|
|
1026
|
-
const subFiles = await listFilesRecursive(fullPath, baseDir, maxDepth - 1);
|
|
1027
|
-
result.push(...subFiles);
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
} catch (error) {}
|
|
1031
|
-
return result;
|
|
1032
|
-
}
|
|
1033
|
-
function filterFileEntries(entries, query) {
|
|
1034
|
-
if (!query) {
|
|
1035
|
-
return entries.slice(0, 20);
|
|
1036
|
-
}
|
|
1037
|
-
const lowerQuery = query.toLowerCase();
|
|
1038
|
-
return entries.filter((e) => e.path.toLowerCase().includes(lowerQuery)).sort((a, b) => {
|
|
1039
|
-
const aLower = a.name.toLowerCase();
|
|
1040
|
-
const bLower = b.name.toLowerCase();
|
|
1041
|
-
if (aLower === lowerQuery && bLower !== lowerQuery) {
|
|
1042
|
-
return -1;
|
|
1043
|
-
}
|
|
1044
|
-
if (bLower === lowerQuery && aLower !== lowerQuery) {
|
|
1045
|
-
return 1;
|
|
1046
|
-
}
|
|
1047
|
-
const aPathLower = a.path.toLowerCase();
|
|
1048
|
-
const bPathLower = b.path.toLowerCase();
|
|
1049
|
-
if (aPathLower.startsWith(lowerQuery) && !bPathLower.startsWith(lowerQuery)) {
|
|
1050
|
-
return -1;
|
|
1051
|
-
}
|
|
1052
|
-
if (bPathLower.startsWith(lowerQuery) && !aPathLower.startsWith(lowerQuery)) {
|
|
1053
|
-
return 1;
|
|
1054
|
-
}
|
|
1055
|
-
return a.path.length - b.path.length;
|
|
1056
|
-
}).slice(0, 20);
|
|
1304
|
+
isPending() {
|
|
1305
|
+
return this.pendingConfirmation !== null;
|
|
1306
|
+
}
|
|
1307
|
+
resetSession() {
|
|
1308
|
+
this.sessionFlags = {
|
|
1309
|
+
fileOperations: false,
|
|
1310
|
+
bashCommands: false,
|
|
1311
|
+
allOperations: false
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
getSessionFlags() {
|
|
1315
|
+
return { ...this.sessionFlags };
|
|
1316
|
+
}
|
|
1317
|
+
setSessionFlag(flagType, value) {
|
|
1318
|
+
this.sessionFlags[flagType] = value;
|
|
1319
|
+
}
|
|
1057
1320
|
}
|
|
1058
1321
|
|
|
1322
|
+
// src/index.ts
|
|
1323
|
+
init_settings_manager();
|
|
1324
|
+
|
|
1325
|
+
// src/hooks/use-input-handler.ts
|
|
1326
|
+
init_file_utils();
|
|
1327
|
+
|
|
1059
1328
|
// src/utils/text-utils.ts
|
|
1060
1329
|
function isWordBoundary(char) {
|
|
1061
1330
|
if (!char) {
|
|
@@ -1499,9 +1768,9 @@ function CommandSuggestions({
|
|
|
1499
1768
|
|
|
1500
1769
|
// src/utils/model-config.ts
|
|
1501
1770
|
init_settings_manager();
|
|
1502
|
-
function loadModelConfig() {
|
|
1771
|
+
function loadModelConfig(providerId) {
|
|
1503
1772
|
const manager = getSettingsManager();
|
|
1504
|
-
const models = manager.getAvailableModels();
|
|
1773
|
+
const models = manager.getAvailableModels(providerId);
|
|
1505
1774
|
return models.map((model) => ({
|
|
1506
1775
|
model: model.trim()
|
|
1507
1776
|
}));
|
|
@@ -2473,7 +2742,7 @@ function getChatManager() {
|
|
|
2473
2742
|
}
|
|
2474
2743
|
|
|
2475
2744
|
// src/hooks/use-input-handler.ts
|
|
2476
|
-
import * as
|
|
2745
|
+
import * as fs8 from "fs-extra";
|
|
2477
2746
|
function useInputHandler({
|
|
2478
2747
|
agent,
|
|
2479
2748
|
chatHistory,
|
|
@@ -2615,6 +2884,7 @@ function useInputHandler({
|
|
|
2615
2884
|
if (providers.length > 0) {
|
|
2616
2885
|
const selectedProviderId = providers[selectedProviderIndex];
|
|
2617
2886
|
manager.updateUserSetting("active_provider", selectedProviderId);
|
|
2887
|
+
setActiveProvider(selectedProviderId);
|
|
2618
2888
|
setChatHistory((prev) => [
|
|
2619
2889
|
...prev,
|
|
2620
2890
|
{
|
|
@@ -2631,6 +2901,24 @@ function useInputHandler({
|
|
|
2631
2901
|
setShowProviderSelection(false);
|
|
2632
2902
|
return true;
|
|
2633
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
|
+
}
|
|
2634
2922
|
return true;
|
|
2635
2923
|
}
|
|
2636
2924
|
if (showConfigViewer) {
|
|
@@ -2826,14 +3114,40 @@ function useInputHandler({
|
|
|
2826
3114
|
description: "Manage plugins (list, install, remove)"
|
|
2827
3115
|
},
|
|
2828
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
|
+
},
|
|
2829
3121
|
{ command: "/exit", description: "Exit the application" }
|
|
2830
3122
|
];
|
|
2831
3123
|
const [activeProvider, setActiveProvider] = useState3(() => {
|
|
2832
3124
|
return getSettingsManager().loadUserSettings().active_provider;
|
|
2833
3125
|
});
|
|
3126
|
+
const [dynamicModels, setDynamicModels] = useState3([]);
|
|
3127
|
+
useEffect(() => {
|
|
3128
|
+
let mounted = true;
|
|
3129
|
+
const fetchModels = async () => {
|
|
3130
|
+
try {
|
|
3131
|
+
const models = await agent.listModels();
|
|
3132
|
+
if (mounted && models.length > 0) {
|
|
3133
|
+
setDynamicModels(models);
|
|
3134
|
+
}
|
|
3135
|
+
} catch (e) {}
|
|
3136
|
+
};
|
|
3137
|
+
fetchModels();
|
|
3138
|
+
return () => {
|
|
3139
|
+
mounted = false;
|
|
3140
|
+
};
|
|
3141
|
+
}, [activeProvider, agent]);
|
|
2834
3142
|
const availableModels = useMemo2(() => {
|
|
2835
|
-
|
|
2836
|
-
|
|
3143
|
+
const configModels = loadModelConfig(activeProvider);
|
|
3144
|
+
if (dynamicModels.length > 0) {
|
|
3145
|
+
const configModelNames = new Set(configModels.map((m) => m.model));
|
|
3146
|
+
const newModels = dynamicModels.filter((m) => !configModelNames.has(m)).map((m) => ({ model: m }));
|
|
3147
|
+
return [...configModels, ...newModels];
|
|
3148
|
+
}
|
|
3149
|
+
return configModels;
|
|
3150
|
+
}, [activeProvider, dynamicModels]);
|
|
2837
3151
|
const handleDirectCommand = async (input2) => {
|
|
2838
3152
|
const trimmedInput = input2.trim();
|
|
2839
3153
|
if (trimmedInput === "/clear") {
|
|
@@ -2887,6 +3201,73 @@ Config Commands:
|
|
|
2887
3201
|
if (trimmedInput === "/exit") {
|
|
2888
3202
|
process.exit(0);
|
|
2889
3203
|
}
|
|
3204
|
+
if (trimmedInput === "/doctor") {
|
|
3205
|
+
setIsProcessing(true);
|
|
3206
|
+
const manager = getSettingsManager();
|
|
3207
|
+
const settings = manager.loadUserSettings();
|
|
3208
|
+
const active = settings.active_provider;
|
|
3209
|
+
const config = settings.providers[active];
|
|
3210
|
+
let checks = `Super Agent Doctor \uD83E\uDE7A
|
|
3211
|
+
|
|
3212
|
+
`;
|
|
3213
|
+
checks += `✅ Active Provider: ${active}
|
|
3214
|
+
`;
|
|
3215
|
+
checks += config ? `✅ Configuration found
|
|
3216
|
+
` : `❌ Configuration MISSING
|
|
3217
|
+
`;
|
|
3218
|
+
checks += config?.api_key ? `✅ API Key set
|
|
3219
|
+
` : `❌ API Key MISSING
|
|
3220
|
+
`;
|
|
3221
|
+
if (active === "workers-ai") {
|
|
3222
|
+
checks += config?.account_id ? `✅ Account ID set
|
|
3223
|
+
` : `❌ Account ID MISSING (use /provider set-account)
|
|
3224
|
+
`;
|
|
3225
|
+
}
|
|
3226
|
+
try {
|
|
3227
|
+
const checkAgent = agent;
|
|
3228
|
+
const models = await checkAgent.listModels();
|
|
3229
|
+
checks += `✅ Connection check: OK (${models.length} models found)
|
|
3230
|
+
`;
|
|
3231
|
+
} catch (e) {
|
|
3232
|
+
checks += `❌ Connection check: FAILED (${e.message})
|
|
3233
|
+
`;
|
|
3234
|
+
}
|
|
3235
|
+
setChatHistory((prev) => [
|
|
3236
|
+
...prev,
|
|
3237
|
+
{
|
|
3238
|
+
type: "assistant",
|
|
3239
|
+
content: checks,
|
|
3240
|
+
timestamp: new Date
|
|
3241
|
+
}
|
|
3242
|
+
]);
|
|
3243
|
+
setIsProcessing(false);
|
|
3244
|
+
clearInput();
|
|
3245
|
+
return true;
|
|
3246
|
+
}
|
|
3247
|
+
if (trimmedInput === "/commands") {
|
|
3248
|
+
setChatHistory((prev) => [
|
|
3249
|
+
...prev,
|
|
3250
|
+
{
|
|
3251
|
+
type: "assistant",
|
|
3252
|
+
content: "Usage: /commands <add|remove|list> [name] [prompt]",
|
|
3253
|
+
timestamp: new Date
|
|
3254
|
+
}
|
|
3255
|
+
]);
|
|
3256
|
+
clearInput();
|
|
3257
|
+
return true;
|
|
3258
|
+
}
|
|
3259
|
+
if (trimmedInput.startsWith("/commands ")) {
|
|
3260
|
+
setChatHistory((prev) => [
|
|
3261
|
+
...prev,
|
|
3262
|
+
{
|
|
3263
|
+
type: "assistant",
|
|
3264
|
+
content: "\uD83D\uDEA7 Custom commands support implies storing them. Feature placeholder.",
|
|
3265
|
+
timestamp: new Date
|
|
3266
|
+
}
|
|
3267
|
+
]);
|
|
3268
|
+
clearInput();
|
|
3269
|
+
return true;
|
|
3270
|
+
}
|
|
2890
3271
|
if (trimmedInput === "/config") {
|
|
2891
3272
|
setShowConfigViewer(true);
|
|
2892
3273
|
clearInput();
|
|
@@ -2898,6 +3279,64 @@ Config Commands:
|
|
|
2898
3279
|
clearInput();
|
|
2899
3280
|
return true;
|
|
2900
3281
|
}
|
|
3282
|
+
if (trimmedInput === "/provider config") {
|
|
3283
|
+
setChatHistory((prev) => [
|
|
3284
|
+
...prev,
|
|
3285
|
+
{
|
|
3286
|
+
type: "assistant",
|
|
3287
|
+
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.",
|
|
3288
|
+
timestamp: new Date
|
|
3289
|
+
}
|
|
3290
|
+
]);
|
|
3291
|
+
clearInput();
|
|
3292
|
+
return true;
|
|
3293
|
+
}
|
|
3294
|
+
if (trimmedInput.startsWith("/provider set-key ")) {
|
|
3295
|
+
const args = trimmedInput.replace("/provider set-key ", "").trim().split(" ");
|
|
3296
|
+
const providerId = args[0];
|
|
3297
|
+
const key = args.slice(1).join(" ");
|
|
3298
|
+
if (!providerId || !key) {
|
|
3299
|
+
setChatHistory((prev) => [
|
|
3300
|
+
...prev,
|
|
3301
|
+
{
|
|
3302
|
+
type: "assistant",
|
|
3303
|
+
content: "❌ Usage: /provider set-key <provider> <api_key>",
|
|
3304
|
+
timestamp: new Date
|
|
3305
|
+
}
|
|
3306
|
+
]);
|
|
3307
|
+
clearInput();
|
|
3308
|
+
return true;
|
|
3309
|
+
}
|
|
3310
|
+
const manager = getSettingsManager();
|
|
3311
|
+
const settings = manager.loadUserSettings();
|
|
3312
|
+
if (settings.providers && settings.providers[providerId]) {
|
|
3313
|
+
const newProviders = { ...settings.providers };
|
|
3314
|
+
newProviders[providerId] = {
|
|
3315
|
+
...newProviders[providerId],
|
|
3316
|
+
api_key: key
|
|
3317
|
+
};
|
|
3318
|
+
manager.updateUserSetting("providers", newProviders);
|
|
3319
|
+
setChatHistory((prev) => [
|
|
3320
|
+
...prev,
|
|
3321
|
+
{
|
|
3322
|
+
type: "assistant",
|
|
3323
|
+
content: `✅ API Key for ${providerId} updated.`,
|
|
3324
|
+
timestamp: new Date
|
|
3325
|
+
}
|
|
3326
|
+
]);
|
|
3327
|
+
} else {
|
|
3328
|
+
setChatHistory((prev) => [
|
|
3329
|
+
...prev,
|
|
3330
|
+
{
|
|
3331
|
+
type: "assistant",
|
|
3332
|
+
content: `❌ Provider '${providerId}' not found.`,
|
|
3333
|
+
timestamp: new Date
|
|
3334
|
+
}
|
|
3335
|
+
]);
|
|
3336
|
+
}
|
|
3337
|
+
clearInput();
|
|
3338
|
+
return true;
|
|
3339
|
+
}
|
|
2901
3340
|
if (trimmedInput.startsWith("/provider use ")) {
|
|
2902
3341
|
const providerId = trimmedInput.replace("/provider use ", "").trim();
|
|
2903
3342
|
const manager = getSettingsManager();
|
|
@@ -2938,6 +3377,57 @@ Config Commands:
|
|
|
2938
3377
|
clearInput();
|
|
2939
3378
|
return true;
|
|
2940
3379
|
}
|
|
3380
|
+
if (trimmedInput.startsWith("/provider set-account ")) {
|
|
3381
|
+
const args = trimmedInput.replace("/provider set-account ", "").trim().split(" ");
|
|
3382
|
+
const providerId = args[0];
|
|
3383
|
+
const accountId = args[1];
|
|
3384
|
+
if (!providerId || !accountId) {
|
|
3385
|
+
setChatHistory((prev) => [
|
|
3386
|
+
...prev,
|
|
3387
|
+
{
|
|
3388
|
+
type: "assistant",
|
|
3389
|
+
content: "❌ Usage: /provider set-account <provider> <account_id>",
|
|
3390
|
+
timestamp: new Date
|
|
3391
|
+
}
|
|
3392
|
+
]);
|
|
3393
|
+
clearInput();
|
|
3394
|
+
return true;
|
|
3395
|
+
}
|
|
3396
|
+
const manager = getSettingsManager();
|
|
3397
|
+
const settings = manager.loadUserSettings();
|
|
3398
|
+
if (settings.providers && settings.providers[providerId]) {
|
|
3399
|
+
const newProviders = { ...settings.providers };
|
|
3400
|
+
newProviders[providerId] = {
|
|
3401
|
+
...newProviders[providerId],
|
|
3402
|
+
account_id: accountId
|
|
3403
|
+
};
|
|
3404
|
+
manager.updateUserSetting("providers", newProviders);
|
|
3405
|
+
setChatHistory((prev) => [
|
|
3406
|
+
...prev,
|
|
3407
|
+
{
|
|
3408
|
+
type: "assistant",
|
|
3409
|
+
content: `✅ Account ID for ${providerId} updated.`,
|
|
3410
|
+
timestamp: new Date
|
|
3411
|
+
}
|
|
3412
|
+
]);
|
|
3413
|
+
if (providerId === activeProvider) {
|
|
3414
|
+
try {
|
|
3415
|
+
agent.setProvider(providerId);
|
|
3416
|
+
} catch (e) {}
|
|
3417
|
+
}
|
|
3418
|
+
} else {
|
|
3419
|
+
setChatHistory((prev) => [
|
|
3420
|
+
...prev,
|
|
3421
|
+
{
|
|
3422
|
+
type: "assistant",
|
|
3423
|
+
content: `❌ Provider '${providerId}' not found.`,
|
|
3424
|
+
timestamp: new Date
|
|
3425
|
+
}
|
|
3426
|
+
]);
|
|
3427
|
+
}
|
|
3428
|
+
clearInput();
|
|
3429
|
+
return true;
|
|
3430
|
+
}
|
|
2941
3431
|
if (trimmedInput.startsWith("/model set ")) {
|
|
2942
3432
|
const modelId = trimmedInput.replace("/model set ", "").trim();
|
|
2943
3433
|
if (modelId) {
|
|
@@ -3071,6 +3561,149 @@ ${chats.length ? chats.map((c) => `- ${c}`).join(`
|
|
|
3071
3561
|
clearInput();
|
|
3072
3562
|
return true;
|
|
3073
3563
|
}
|
|
3564
|
+
if (trimmedInput.startsWith("/import ")) {
|
|
3565
|
+
const args = trimmedInput.replace("/import ", "").split(" ");
|
|
3566
|
+
const type = args[0];
|
|
3567
|
+
const source = args[1];
|
|
3568
|
+
if (!type || !source) {
|
|
3569
|
+
setChatHistory((prev) => [
|
|
3570
|
+
...prev,
|
|
3571
|
+
{
|
|
3572
|
+
type: "assistant",
|
|
3573
|
+
content: `❌ Usage: /import <type> <source>
|
|
3574
|
+
Types: agents, skills, hooks
|
|
3575
|
+
Sources: gemini, claude, kilo, or path`,
|
|
3576
|
+
timestamp: new Date
|
|
3577
|
+
}
|
|
3578
|
+
]);
|
|
3579
|
+
clearInput();
|
|
3580
|
+
return true;
|
|
3581
|
+
}
|
|
3582
|
+
setIsProcessing(true);
|
|
3583
|
+
setChatHistory((prev) => [
|
|
3584
|
+
...prev,
|
|
3585
|
+
{
|
|
3586
|
+
type: "assistant",
|
|
3587
|
+
content: `Importing ${type} from ${source}...`,
|
|
3588
|
+
timestamp: new Date
|
|
3589
|
+
}
|
|
3590
|
+
]);
|
|
3591
|
+
try {
|
|
3592
|
+
const { resolveSourcePath: resolveSourcePath2 } = await Promise.resolve().then(() => (init_file_utils(), exports_file_utils));
|
|
3593
|
+
const { AgentsManager: AgentsManager2 } = await Promise.resolve().then(() => (init_manager(), exports_manager));
|
|
3594
|
+
const { SkillsManager: SkillsManager2 } = await Promise.resolve().then(() => (init_manager2(), exports_manager2));
|
|
3595
|
+
const { getSettingsManager: getSettingsManager2 } = await Promise.resolve().then(() => (init_settings_manager(), exports_settings_manager));
|
|
3596
|
+
const fs9 = await import("fs-extra");
|
|
3597
|
+
const path8 = await import("path");
|
|
3598
|
+
const sourcePath = resolveSourcePath2(source);
|
|
3599
|
+
if (type === "agents") {
|
|
3600
|
+
const agentsDir = path8.join(sourcePath, "agents");
|
|
3601
|
+
if (!await fs9.pathExists(agentsDir)) {
|
|
3602
|
+
throw new Error(`Agents directory not found at ${agentsDir}`);
|
|
3603
|
+
}
|
|
3604
|
+
const files = await fs9.readdir(agentsDir);
|
|
3605
|
+
const manager = AgentsManager2.getInstance();
|
|
3606
|
+
let count = 0;
|
|
3607
|
+
for (const file of files) {
|
|
3608
|
+
if (file.endsWith(".json")) {
|
|
3609
|
+
try {
|
|
3610
|
+
const content = await fs9.readJson(path8.join(agentsDir, file));
|
|
3611
|
+
const agentConfig = {
|
|
3612
|
+
name: content.name || path8.parse(file).name,
|
|
3613
|
+
role: content.role || "Assistant",
|
|
3614
|
+
description: content.description || "Imported agent",
|
|
3615
|
+
model: content.model,
|
|
3616
|
+
tools: content.tools,
|
|
3617
|
+
temperature: content.temperature,
|
|
3618
|
+
systemPrompt: content.systemPrompt || content.system_prompt || content.prompt
|
|
3619
|
+
};
|
|
3620
|
+
await manager.createAgent(agentConfig);
|
|
3621
|
+
count++;
|
|
3622
|
+
} catch (e) {}
|
|
3623
|
+
}
|
|
3624
|
+
}
|
|
3625
|
+
setChatHistory((prev) => [
|
|
3626
|
+
...prev,
|
|
3627
|
+
{
|
|
3628
|
+
type: "assistant",
|
|
3629
|
+
content: `✅ Imported ${count} agents.`,
|
|
3630
|
+
timestamp: new Date
|
|
3631
|
+
}
|
|
3632
|
+
]);
|
|
3633
|
+
} else if (type === "skills") {
|
|
3634
|
+
const skillsDir = path8.join(sourcePath, "skills");
|
|
3635
|
+
if (!await fs9.pathExists(skillsDir)) {
|
|
3636
|
+
throw new Error(`Skills directory not found at ${skillsDir}`);
|
|
3637
|
+
}
|
|
3638
|
+
const files = await fs9.readdir(skillsDir);
|
|
3639
|
+
const manager = SkillsManager2.getInstance();
|
|
3640
|
+
let count = 0;
|
|
3641
|
+
for (const file of files) {
|
|
3642
|
+
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
3643
|
+
try {
|
|
3644
|
+
const content = await fs9.readFile(path8.join(skillsDir, file), "utf-8");
|
|
3645
|
+
const name = path8.parse(file).name;
|
|
3646
|
+
await manager.saveSkill(name, content);
|
|
3647
|
+
count++;
|
|
3648
|
+
} catch (e) {}
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
setChatHistory((prev) => [
|
|
3652
|
+
...prev,
|
|
3653
|
+
{
|
|
3654
|
+
type: "assistant",
|
|
3655
|
+
content: `✅ Imported ${count} skills.`,
|
|
3656
|
+
timestamp: new Date
|
|
3657
|
+
}
|
|
3658
|
+
]);
|
|
3659
|
+
} else if (type === "hooks") {
|
|
3660
|
+
const settingsFile = source.toLowerCase() === "claude" ? "settings.local.json" : "settings.json";
|
|
3661
|
+
const fullPath = path8.join(sourcePath, settingsFile);
|
|
3662
|
+
if (!await fs9.pathExists(fullPath)) {
|
|
3663
|
+
throw new Error(`Settings file not found at ${fullPath}`);
|
|
3664
|
+
}
|
|
3665
|
+
const settings = await fs9.readJson(fullPath);
|
|
3666
|
+
if (settings.hooks) {
|
|
3667
|
+
const manager = getSettingsManager2();
|
|
3668
|
+
const currentHooks = manager.getUserSetting("hooks") || {};
|
|
3669
|
+
const mergedHooks = { ...currentHooks, ...settings.hooks };
|
|
3670
|
+
manager.updateUserSetting("hooks", mergedHooks);
|
|
3671
|
+
setChatHistory((prev) => [
|
|
3672
|
+
...prev,
|
|
3673
|
+
{
|
|
3674
|
+
type: "assistant",
|
|
3675
|
+
content: `✅ Imported ${Object.keys(settings.hooks).length} hooks.`,
|
|
3676
|
+
timestamp: new Date
|
|
3677
|
+
}
|
|
3678
|
+
]);
|
|
3679
|
+
} else {
|
|
3680
|
+
setChatHistory((prev) => [
|
|
3681
|
+
...prev,
|
|
3682
|
+
{
|
|
3683
|
+
type: "assistant",
|
|
3684
|
+
content: "⚠️ No hooks found in settings file.",
|
|
3685
|
+
timestamp: new Date
|
|
3686
|
+
}
|
|
3687
|
+
]);
|
|
3688
|
+
}
|
|
3689
|
+
} else {
|
|
3690
|
+
throw new Error(`Unknown import type: ${type}`);
|
|
3691
|
+
}
|
|
3692
|
+
} catch (error) {
|
|
3693
|
+
setChatHistory((prev) => [
|
|
3694
|
+
...prev,
|
|
3695
|
+
{
|
|
3696
|
+
type: "assistant",
|
|
3697
|
+
content: `❌ Import failed: ${error.message}`,
|
|
3698
|
+
timestamp: new Date
|
|
3699
|
+
}
|
|
3700
|
+
]);
|
|
3701
|
+
} finally {
|
|
3702
|
+
setIsProcessing(false);
|
|
3703
|
+
}
|
|
3704
|
+
clearInput();
|
|
3705
|
+
return true;
|
|
3706
|
+
}
|
|
3074
3707
|
if (trimmedInput.startsWith("/plugin ")) {
|
|
3075
3708
|
const args = trimmedInput.replace("/plugin ", "").split(" ");
|
|
3076
3709
|
const action = args[0];
|
|
@@ -3487,9 +4120,9 @@ ${commitMessage}`
|
|
|
3487
4120
|
for (const mention of mentionMatches) {
|
|
3488
4121
|
const filePath = mention.slice(1);
|
|
3489
4122
|
try {
|
|
3490
|
-
const stats = await
|
|
4123
|
+
const stats = await fs8.stat(filePath);
|
|
3491
4124
|
if (stats.isFile()) {
|
|
3492
|
-
const content = await
|
|
4125
|
+
const content = await fs8.readFile(filePath, "utf-8");
|
|
3493
4126
|
resolvedInput = resolvedInput.replace(mention, `
|
|
3494
4127
|
|
|
3495
4128
|
--- FILE: ${filePath} ---
|
|
@@ -3640,6 +4273,7 @@ ${structure}
|
|
|
3640
4273
|
}
|
|
3641
4274
|
|
|
3642
4275
|
// src/ui/components/mention-suggestions.tsx
|
|
4276
|
+
init_file_utils();
|
|
3643
4277
|
import { useMemo as useMemo3 } from "react";
|
|
3644
4278
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
3645
4279
|
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
@@ -4417,6 +5051,7 @@ function LoadingSpinner({
|
|
|
4417
5051
|
}
|
|
4418
5052
|
|
|
4419
5053
|
// src/ui/components/command-palette.tsx
|
|
5054
|
+
init_file_utils();
|
|
4420
5055
|
import { useMemo as useMemo4 } from "react";
|
|
4421
5056
|
import { Box as Box9, Text as Text8 } from "ink";
|
|
4422
5057
|
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
@@ -5055,8 +5690,8 @@ class ConfirmationTool {
|
|
|
5055
5690
|
}
|
|
5056
5691
|
}
|
|
5057
5692
|
// src/tools/morph-editor.ts
|
|
5058
|
-
import * as
|
|
5059
|
-
import
|
|
5693
|
+
import * as path8 from "path";
|
|
5694
|
+
import fs9 from "fs-extra";
|
|
5060
5695
|
import axios2 from "axios";
|
|
5061
5696
|
|
|
5062
5697
|
class MorphEditorTool {
|
|
@@ -5071,8 +5706,8 @@ class MorphEditorTool {
|
|
|
5071
5706
|
}
|
|
5072
5707
|
async editFile(targetFile, instructions, codeEdit) {
|
|
5073
5708
|
try {
|
|
5074
|
-
const resolvedPath =
|
|
5075
|
-
if (!await
|
|
5709
|
+
const resolvedPath = path8.resolve(targetFile);
|
|
5710
|
+
if (!await fs9.pathExists(resolvedPath)) {
|
|
5076
5711
|
return {
|
|
5077
5712
|
success: false,
|
|
5078
5713
|
error: `File not found: ${targetFile}`
|
|
@@ -5084,7 +5719,7 @@ class MorphEditorTool {
|
|
|
5084
5719
|
error: "MORPH_API_KEY not configured. Please set your Morph API key."
|
|
5085
5720
|
};
|
|
5086
5721
|
}
|
|
5087
|
-
const initialCode = await
|
|
5722
|
+
const initialCode = await fs9.readFile(resolvedPath, "utf-8");
|
|
5088
5723
|
const sessionFlags = this.confirmationService.getSessionFlags();
|
|
5089
5724
|
if (!sessionFlags.fileOperations && !sessionFlags.allOperations) {
|
|
5090
5725
|
const confirmationResult = await this.confirmationService.requestConfirmation({
|
|
@@ -5104,7 +5739,7 @@ ${codeEdit}`
|
|
|
5104
5739
|
}
|
|
5105
5740
|
}
|
|
5106
5741
|
const mergedCode = await this.callMorphApply(instructions, initialCode, codeEdit);
|
|
5107
|
-
await
|
|
5742
|
+
await fs9.writeFile(resolvedPath, mergedCode, "utf-8");
|
|
5108
5743
|
const oldLines = initialCode.split(`
|
|
5109
5744
|
`);
|
|
5110
5745
|
const newLines = mergedCode.split(`
|
|
@@ -5287,11 +5922,11 @@ ${codeEdit}`
|
|
|
5287
5922
|
}
|
|
5288
5923
|
async view(filePath, viewRange) {
|
|
5289
5924
|
try {
|
|
5290
|
-
const resolvedPath =
|
|
5291
|
-
if (await
|
|
5292
|
-
const stats = await
|
|
5925
|
+
const resolvedPath = path8.resolve(filePath);
|
|
5926
|
+
if (await fs9.pathExists(resolvedPath)) {
|
|
5927
|
+
const stats = await fs9.stat(resolvedPath);
|
|
5293
5928
|
if (stats.isDirectory()) {
|
|
5294
|
-
const files = await
|
|
5929
|
+
const files = await fs9.readdir(resolvedPath);
|
|
5295
5930
|
return {
|
|
5296
5931
|
success: true,
|
|
5297
5932
|
output: `Directory contents of ${filePath}:
|
|
@@ -5299,7 +5934,7 @@ ${files.join(`
|
|
|
5299
5934
|
`)}`
|
|
5300
5935
|
};
|
|
5301
5936
|
}
|
|
5302
|
-
const content = await
|
|
5937
|
+
const content = await fs9.readFile(resolvedPath, "utf-8");
|
|
5303
5938
|
const lines = content.split(`
|
|
5304
5939
|
`);
|
|
5305
5940
|
if (viewRange) {
|
|
@@ -5345,8 +5980,8 @@ ${numberedLines}${additionalLinesMessage}`
|
|
|
5345
5980
|
}
|
|
5346
5981
|
}
|
|
5347
5982
|
// src/tools/project-map.ts
|
|
5348
|
-
import * as
|
|
5349
|
-
import
|
|
5983
|
+
import * as path9 from "path";
|
|
5984
|
+
import fs10 from "fs-extra";
|
|
5350
5985
|
|
|
5351
5986
|
class ProjectMapTool {
|
|
5352
5987
|
currentDirectory = process.cwd();
|
|
@@ -5380,7 +6015,7 @@ Important Files:
|
|
|
5380
6015
|
}
|
|
5381
6016
|
let result = "";
|
|
5382
6017
|
try {
|
|
5383
|
-
const entries = await
|
|
6018
|
+
const entries = await fs10.readdir(dir, { withFileTypes: true });
|
|
5384
6019
|
const sortedEntries = entries.sort((a, b) => {
|
|
5385
6020
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
5386
6021
|
return -1;
|
|
@@ -5408,7 +6043,7 @@ Important Files:
|
|
|
5408
6043
|
if (entry.isDirectory()) {
|
|
5409
6044
|
result += `${indent}\uD83D\uDCC1 ${entry.name}/
|
|
5410
6045
|
`;
|
|
5411
|
-
result += await this.generateTree(
|
|
6046
|
+
result += await this.generateTree(path9.join(dir, entry.name), maxDepth, currentDepth + 1);
|
|
5412
6047
|
} else {
|
|
5413
6048
|
result += `${indent}\uD83D\uDCC4 ${entry.name}
|
|
5414
6049
|
`;
|
|
@@ -5430,8 +6065,8 @@ Important Files:
|
|
|
5430
6065
|
];
|
|
5431
6066
|
const found = [];
|
|
5432
6067
|
for (const pattern of importantPatterns) {
|
|
5433
|
-
const fullPath =
|
|
5434
|
-
if (await
|
|
6068
|
+
const fullPath = path9.join(this.currentDirectory, pattern);
|
|
6069
|
+
if (await fs10.pathExists(fullPath)) {
|
|
5435
6070
|
found.push(pattern);
|
|
5436
6071
|
}
|
|
5437
6072
|
}
|
|
@@ -5444,8 +6079,8 @@ Important Files:
|
|
|
5444
6079
|
// src/tools/search.ts
|
|
5445
6080
|
init_indexer();
|
|
5446
6081
|
import { spawn } from "child_process";
|
|
5447
|
-
import * as
|
|
5448
|
-
import
|
|
6082
|
+
import * as path11 from "path";
|
|
6083
|
+
import fs12 from "fs-extra";
|
|
5449
6084
|
|
|
5450
6085
|
class SearchTool {
|
|
5451
6086
|
confirmationService = ConfirmationService.getInstance();
|
|
@@ -5474,7 +6109,7 @@ class SearchTool {
|
|
|
5474
6109
|
const searchPattern = query.toLowerCase();
|
|
5475
6110
|
fileResults = entries.filter((e) => e.path.toLowerCase().includes(searchPattern)).map((e) => ({
|
|
5476
6111
|
path: e.path,
|
|
5477
|
-
name:
|
|
6112
|
+
name: path11.basename(e.path),
|
|
5478
6113
|
score: 10
|
|
5479
6114
|
}));
|
|
5480
6115
|
} else {
|
|
@@ -5598,13 +6233,13 @@ class SearchTool {
|
|
|
5598
6233
|
return;
|
|
5599
6234
|
}
|
|
5600
6235
|
try {
|
|
5601
|
-
const entries = await
|
|
6236
|
+
const entries = await fs12.readdir(dir, { withFileTypes: true });
|
|
5602
6237
|
for (const entry of entries) {
|
|
5603
6238
|
if (files.length >= maxResults) {
|
|
5604
6239
|
break;
|
|
5605
6240
|
}
|
|
5606
|
-
const fullPath =
|
|
5607
|
-
const relativePath =
|
|
6241
|
+
const fullPath = path11.join(dir, entry.name);
|
|
6242
|
+
const relativePath = path11.relative(this.currentDirectory, fullPath);
|
|
5608
6243
|
if (!options.includeHidden && entry.name.startsWith(".")) {
|
|
5609
6244
|
continue;
|
|
5610
6245
|
}
|
|
@@ -5703,19 +6338,19 @@ class SearchTool {
|
|
|
5703
6338
|
}
|
|
5704
6339
|
// src/tools/text-editor.ts
|
|
5705
6340
|
import { writeFile as writeFilePromise } from "fs/promises";
|
|
5706
|
-
import * as
|
|
5707
|
-
import
|
|
6341
|
+
import * as path12 from "path";
|
|
6342
|
+
import fs13 from "fs-extra";
|
|
5708
6343
|
|
|
5709
6344
|
class TextEditorTool {
|
|
5710
6345
|
editHistory = [];
|
|
5711
6346
|
confirmationService = ConfirmationService.getInstance();
|
|
5712
6347
|
async view(filePath, viewRange) {
|
|
5713
6348
|
try {
|
|
5714
|
-
const resolvedPath =
|
|
5715
|
-
if (await
|
|
5716
|
-
const stats = await
|
|
6349
|
+
const resolvedPath = path12.resolve(filePath);
|
|
6350
|
+
if (await fs13.pathExists(resolvedPath)) {
|
|
6351
|
+
const stats = await fs13.stat(resolvedPath);
|
|
5717
6352
|
if (stats.isDirectory()) {
|
|
5718
|
-
const files = await
|
|
6353
|
+
const files = await fs13.readdir(resolvedPath);
|
|
5719
6354
|
return {
|
|
5720
6355
|
success: true,
|
|
5721
6356
|
output: `Directory contents of ${filePath}:
|
|
@@ -5723,7 +6358,7 @@ ${files.join(`
|
|
|
5723
6358
|
`)}`
|
|
5724
6359
|
};
|
|
5725
6360
|
}
|
|
5726
|
-
const content = await
|
|
6361
|
+
const content = await fs13.readFile(resolvedPath, "utf-8");
|
|
5727
6362
|
const lines = content.split(`
|
|
5728
6363
|
`);
|
|
5729
6364
|
if (viewRange) {
|
|
@@ -5763,14 +6398,14 @@ ${numberedLines}${additionalLinesMessage}`
|
|
|
5763
6398
|
}
|
|
5764
6399
|
async strReplace(filePath, oldStr, newStr, replaceAll = false) {
|
|
5765
6400
|
try {
|
|
5766
|
-
const resolvedPath =
|
|
5767
|
-
if (!await
|
|
6401
|
+
const resolvedPath = path12.resolve(filePath);
|
|
6402
|
+
if (!await fs13.pathExists(resolvedPath)) {
|
|
5768
6403
|
return {
|
|
5769
6404
|
success: false,
|
|
5770
6405
|
error: `File not found: ${filePath}`
|
|
5771
6406
|
};
|
|
5772
6407
|
}
|
|
5773
|
-
const content = await
|
|
6408
|
+
const content = await fs13.readFile(resolvedPath, "utf-8");
|
|
5774
6409
|
if (!content.includes(oldStr)) {
|
|
5775
6410
|
if (oldStr.includes(`
|
|
5776
6411
|
`)) {
|
|
@@ -5838,7 +6473,7 @@ ${numberedLines}${additionalLinesMessage}`
|
|
|
5838
6473
|
}
|
|
5839
6474
|
async create(filePath, content) {
|
|
5840
6475
|
try {
|
|
5841
|
-
const resolvedPath =
|
|
6476
|
+
const resolvedPath = path12.resolve(filePath);
|
|
5842
6477
|
const sessionFlags = this.confirmationService.getSessionFlags();
|
|
5843
6478
|
if (!sessionFlags.fileOperations && !sessionFlags.allOperations) {
|
|
5844
6479
|
const contentLines = content.split(`
|
|
@@ -5864,8 +6499,8 @@ ${numberedLines}${additionalLinesMessage}`
|
|
|
5864
6499
|
};
|
|
5865
6500
|
}
|
|
5866
6501
|
}
|
|
5867
|
-
const dir =
|
|
5868
|
-
await
|
|
6502
|
+
const dir = path12.dirname(resolvedPath);
|
|
6503
|
+
await fs13.ensureDir(dir);
|
|
5869
6504
|
await writeFilePromise(resolvedPath, content, "utf-8");
|
|
5870
6505
|
this.editHistory.push({
|
|
5871
6506
|
command: "create",
|
|
@@ -5889,14 +6524,14 @@ ${numberedLines}${additionalLinesMessage}`
|
|
|
5889
6524
|
}
|
|
5890
6525
|
async replaceLines(filePath, startLine, endLine, newContent) {
|
|
5891
6526
|
try {
|
|
5892
|
-
const resolvedPath =
|
|
5893
|
-
if (!await
|
|
6527
|
+
const resolvedPath = path12.resolve(filePath);
|
|
6528
|
+
if (!await fs13.pathExists(resolvedPath)) {
|
|
5894
6529
|
return {
|
|
5895
6530
|
success: false,
|
|
5896
6531
|
error: `File not found: ${filePath}`
|
|
5897
6532
|
};
|
|
5898
6533
|
}
|
|
5899
|
-
const fileContent = await
|
|
6534
|
+
const fileContent = await fs13.readFile(resolvedPath, "utf-8");
|
|
5900
6535
|
const lines = fileContent.split(`
|
|
5901
6536
|
`);
|
|
5902
6537
|
if (startLine < 1 || startLine > lines.length) {
|
|
@@ -5959,14 +6594,14 @@ ${numberedLines}${additionalLinesMessage}`
|
|
|
5959
6594
|
}
|
|
5960
6595
|
async insert(filePath, insertLine, content) {
|
|
5961
6596
|
try {
|
|
5962
|
-
const resolvedPath =
|
|
5963
|
-
if (!await
|
|
6597
|
+
const resolvedPath = path12.resolve(filePath);
|
|
6598
|
+
if (!await fs13.pathExists(resolvedPath)) {
|
|
5964
6599
|
return {
|
|
5965
6600
|
success: false,
|
|
5966
6601
|
error: `File not found: ${filePath}`
|
|
5967
6602
|
};
|
|
5968
6603
|
}
|
|
5969
|
-
const fileContent = await
|
|
6604
|
+
const fileContent = await fs13.readFile(resolvedPath, "utf-8");
|
|
5970
6605
|
const lines = fileContent.split(`
|
|
5971
6606
|
`);
|
|
5972
6607
|
lines.splice(insertLine - 1, 0, content);
|
|
@@ -6002,19 +6637,19 @@ ${numberedLines}${additionalLinesMessage}`
|
|
|
6002
6637
|
switch (lastEdit.command) {
|
|
6003
6638
|
case "str_replace":
|
|
6004
6639
|
if (lastEdit.path && lastEdit.old_str && lastEdit.new_str) {
|
|
6005
|
-
const content = await
|
|
6640
|
+
const content = await fs13.readFile(lastEdit.path, "utf-8");
|
|
6006
6641
|
const revertedContent = content.replace(lastEdit.new_str, lastEdit.old_str);
|
|
6007
6642
|
await writeFilePromise(lastEdit.path, revertedContent, "utf-8");
|
|
6008
6643
|
}
|
|
6009
6644
|
break;
|
|
6010
6645
|
case "create":
|
|
6011
6646
|
if (lastEdit.path) {
|
|
6012
|
-
await
|
|
6647
|
+
await fs13.remove(lastEdit.path);
|
|
6013
6648
|
}
|
|
6014
6649
|
break;
|
|
6015
6650
|
case "insert":
|
|
6016
6651
|
if (lastEdit.path && lastEdit.insert_line) {
|
|
6017
|
-
const content = await
|
|
6652
|
+
const content = await fs13.readFile(lastEdit.path, "utf-8");
|
|
6018
6653
|
const lines = content.split(`
|
|
6019
6654
|
`);
|
|
6020
6655
|
lines.splice(lastEdit.insert_line - 1, 1);
|
|
@@ -6456,22 +7091,30 @@ class OpenAICompatibleProvider {
|
|
|
6456
7091
|
throw new Error(`${this.name} API error: ${error.message}`);
|
|
6457
7092
|
}
|
|
6458
7093
|
}
|
|
7094
|
+
async listModels() {
|
|
7095
|
+
try {
|
|
7096
|
+
const response = await this.client.models.list();
|
|
7097
|
+
return response.data.map((m) => m.id);
|
|
7098
|
+
} catch (error) {
|
|
7099
|
+
return [];
|
|
7100
|
+
}
|
|
7101
|
+
}
|
|
6459
7102
|
}
|
|
6460
7103
|
|
|
6461
7104
|
// src/utils/custom-instructions.ts
|
|
6462
|
-
import * as
|
|
6463
|
-
import * as
|
|
6464
|
-
import * as
|
|
7105
|
+
import * as path13 from "path";
|
|
7106
|
+
import * as os3 from "os";
|
|
7107
|
+
import * as fs14 from "fs";
|
|
6465
7108
|
function loadCustomInstructions(workingDirectory = process.cwd()) {
|
|
6466
7109
|
try {
|
|
6467
|
-
let instructionsPath =
|
|
6468
|
-
if (
|
|
6469
|
-
const customInstructions =
|
|
7110
|
+
let instructionsPath = path13.join(workingDirectory, ".super-agent", "SUPER_AGENT.md");
|
|
7111
|
+
if (fs14.existsSync(instructionsPath)) {
|
|
7112
|
+
const customInstructions = fs14.readFileSync(instructionsPath, "utf-8");
|
|
6470
7113
|
return customInstructions.trim();
|
|
6471
7114
|
}
|
|
6472
|
-
instructionsPath =
|
|
6473
|
-
if (
|
|
6474
|
-
const customInstructions =
|
|
7115
|
+
instructionsPath = path13.join(os3.homedir(), ".super-agent", "SUPER_AGENT.md");
|
|
7116
|
+
if (fs14.existsSync(instructionsPath)) {
|
|
7117
|
+
const customInstructions = fs14.readFileSync(instructionsPath, "utf-8");
|
|
6475
7118
|
return customInstructions.trim();
|
|
6476
7119
|
}
|
|
6477
7120
|
return null;
|
|
@@ -6547,6 +7190,14 @@ class OpenAIProvider {
|
|
|
6547
7190
|
throw new Error(`OpenAI API error: ${error.message}`);
|
|
6548
7191
|
}
|
|
6549
7192
|
}
|
|
7193
|
+
async listModels() {
|
|
7194
|
+
try {
|
|
7195
|
+
const response = await this.client.models.list();
|
|
7196
|
+
return response.data.map((m) => m.id);
|
|
7197
|
+
} catch (error) {
|
|
7198
|
+
return [];
|
|
7199
|
+
}
|
|
7200
|
+
}
|
|
6550
7201
|
}
|
|
6551
7202
|
|
|
6552
7203
|
// src/core/providers/gemini.ts
|
|
@@ -6710,6 +7361,9 @@ class GeminiProvider {
|
|
|
6710
7361
|
throw new Error(`Gemini API error: ${error.message}`);
|
|
6711
7362
|
}
|
|
6712
7363
|
}
|
|
7364
|
+
async listModels() {
|
|
7365
|
+
return [];
|
|
7366
|
+
}
|
|
6713
7367
|
}
|
|
6714
7368
|
|
|
6715
7369
|
// src/core/providers/grok.ts
|
|
@@ -6778,7 +7432,15 @@ class GrokProvider {
|
|
|
6778
7432
|
yield chunk;
|
|
6779
7433
|
}
|
|
6780
7434
|
} catch (error) {
|
|
6781
|
-
throw new Error(`Grok API error: ${error.message}`);
|
|
7435
|
+
throw new Error(`Grok API error: ${error.message}`);
|
|
7436
|
+
}
|
|
7437
|
+
}
|
|
7438
|
+
async listModels() {
|
|
7439
|
+
try {
|
|
7440
|
+
const response = await this.client.models.list();
|
|
7441
|
+
return response.data.map((m) => m.id);
|
|
7442
|
+
} catch (error) {
|
|
7443
|
+
return [];
|
|
6782
7444
|
}
|
|
6783
7445
|
}
|
|
6784
7446
|
}
|
|
@@ -6814,7 +7476,12 @@ class SuperAgent extends EventEmitter4 {
|
|
|
6814
7476
|
const providerConfig = settings.providers[activeProviderId];
|
|
6815
7477
|
const providerType = providerConfig?.provider || activeProviderId;
|
|
6816
7478
|
const effectiveApiKey = apiKey || providerConfig?.api_key || "";
|
|
6817
|
-
|
|
7479
|
+
let effectiveBaseURL = baseURL || (providerConfig?.base_url ? providerConfig.base_url : undefined);
|
|
7480
|
+
if (providerConfig?.provider === "workers-ai" && effectiveBaseURL?.includes("{ACCOUNT_ID}")) {
|
|
7481
|
+
if (providerConfig.account_id) {
|
|
7482
|
+
effectiveBaseURL = effectiveBaseURL.replace("{ACCOUNT_ID}", providerConfig.account_id);
|
|
7483
|
+
}
|
|
7484
|
+
}
|
|
6818
7485
|
const effectiveModel = model || providerConfig?.model || providerConfig?.default_model || "grok-code-fast-1";
|
|
6819
7486
|
this.maxToolRounds = maxToolRounds || 400;
|
|
6820
7487
|
if (providerType === "openai") {
|
|
@@ -6919,7 +7586,12 @@ Current working directory: ${process.cwd()}`
|
|
|
6919
7586
|
}
|
|
6920
7587
|
const providerType = providerConfig.provider || activeProviderId;
|
|
6921
7588
|
const effectiveApiKey = providerConfig.api_key || "";
|
|
6922
|
-
|
|
7589
|
+
let effectiveBaseURL = providerConfig.base_url || undefined;
|
|
7590
|
+
if (providerConfig.provider === "workers-ai" && effectiveBaseURL?.includes("{ACCOUNT_ID}")) {
|
|
7591
|
+
if (providerConfig.account_id) {
|
|
7592
|
+
effectiveBaseURL = effectiveBaseURL.replace("{ACCOUNT_ID}", providerConfig.account_id);
|
|
7593
|
+
}
|
|
7594
|
+
}
|
|
6923
7595
|
const effectiveModel = providerConfig.model || providerConfig.default_model || "grok-code-fast-1";
|
|
6924
7596
|
if (providerType === "openai") {
|
|
6925
7597
|
this.superAgentClient = new OpenAIProvider(effectiveApiKey, effectiveBaseURL, effectiveModel);
|
|
@@ -6932,6 +7604,12 @@ Current working directory: ${process.cwd()}`
|
|
|
6932
7604
|
}
|
|
6933
7605
|
this.tokenCounter = createTokenCounter(effectiveModel);
|
|
6934
7606
|
}
|
|
7607
|
+
async listModels() {
|
|
7608
|
+
if (this.superAgentClient.listModels) {
|
|
7609
|
+
return this.superAgentClient.listModels();
|
|
7610
|
+
}
|
|
7611
|
+
return [];
|
|
7612
|
+
}
|
|
6935
7613
|
async initializeMCP() {
|
|
6936
7614
|
Promise.resolve().then(async () => {
|
|
6937
7615
|
try {
|
|
@@ -8180,8 +8858,8 @@ init_settings_manager();
|
|
|
8180
8858
|
// src/web/server.ts
|
|
8181
8859
|
import { createServer } from "http";
|
|
8182
8860
|
import { WebSocketServer } from "ws";
|
|
8183
|
-
import * as
|
|
8184
|
-
import * as
|
|
8861
|
+
import * as fs17 from "fs-extra";
|
|
8862
|
+
import * as path16 from "path";
|
|
8185
8863
|
import open from "open";
|
|
8186
8864
|
import mime from "mime";
|
|
8187
8865
|
var __dirname = "/home/runner/work/super-agent-cli/super-agent-cli/src/web";
|
|
@@ -8209,21 +8887,21 @@ class WebServer {
|
|
|
8209
8887
|
const url = req.url || "/";
|
|
8210
8888
|
const requestedPath = url === "/" ? "index.html" : url;
|
|
8211
8889
|
const sanitizedPath = requestedPath.split("?")[0].split("#")[0];
|
|
8212
|
-
const clientDir =
|
|
8213
|
-
const absolutePath =
|
|
8890
|
+
const clientDir = path16.join(__dirname, "../web/client");
|
|
8891
|
+
const absolutePath = path16.resolve(clientDir, sanitizedPath.substring(1));
|
|
8214
8892
|
if (!absolutePath.startsWith(clientDir)) {
|
|
8215
8893
|
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
8216
8894
|
res.end("Forbidden");
|
|
8217
8895
|
return;
|
|
8218
8896
|
}
|
|
8219
8897
|
try {
|
|
8220
|
-
if (await
|
|
8221
|
-
const stat5 = await
|
|
8898
|
+
if (await fs17.pathExists(absolutePath)) {
|
|
8899
|
+
const stat5 = await fs17.stat(absolutePath);
|
|
8222
8900
|
let filePath = absolutePath;
|
|
8223
8901
|
if (stat5.isDirectory()) {
|
|
8224
|
-
filePath =
|
|
8902
|
+
filePath = path16.join(absolutePath, "index.html");
|
|
8225
8903
|
}
|
|
8226
|
-
const content = await
|
|
8904
|
+
const content = await fs17.readFile(filePath);
|
|
8227
8905
|
const mimeType = mime.getType(filePath) || "application/octet-stream";
|
|
8228
8906
|
res.writeHead(200, { "Content-Type": mimeType });
|
|
8229
8907
|
res.end(content);
|
|
@@ -8311,7 +8989,7 @@ class WebServer {
|
|
|
8311
8989
|
}
|
|
8312
8990
|
const tree = index.entries.filter((e) => !e.path.includes("node_modules") && !e.path.startsWith(".")).map((e) => ({
|
|
8313
8991
|
path: e.path,
|
|
8314
|
-
name:
|
|
8992
|
+
name: path16.basename(e.path),
|
|
8315
8993
|
isDirectory: e.isDirectory,
|
|
8316
8994
|
size: e.size
|
|
8317
8995
|
})).slice(0, 500);
|
|
@@ -8322,11 +9000,11 @@ class WebServer {
|
|
|
8322
9000
|
}
|
|
8323
9001
|
async handleGetFileContent(filePath, ws) {
|
|
8324
9002
|
try {
|
|
8325
|
-
const fullPath =
|
|
9003
|
+
const fullPath = path16.join(process.cwd(), filePath);
|
|
8326
9004
|
if (!fullPath.startsWith(process.cwd())) {
|
|
8327
9005
|
throw new Error("Access denied");
|
|
8328
9006
|
}
|
|
8329
|
-
const content = await
|
|
9007
|
+
const content = await fs17.readFile(fullPath, "utf-8");
|
|
8330
9008
|
ws.send(JSON.stringify({
|
|
8331
9009
|
type: "file_content",
|
|
8332
9010
|
path: filePath,
|
|
@@ -8480,12 +9158,133 @@ function createServeCommand() {
|
|
|
8480
9158
|
return serveCommand;
|
|
8481
9159
|
}
|
|
8482
9160
|
|
|
8483
|
-
// src/commands/
|
|
9161
|
+
// src/commands/provider.ts
|
|
9162
|
+
init_settings_manager();
|
|
8484
9163
|
import { Command as Command2 } from "commander";
|
|
8485
|
-
import
|
|
8486
|
-
import ignore from "ignore";
|
|
9164
|
+
import inquirer from "inquirer";
|
|
8487
9165
|
import chalk2 from "chalk";
|
|
8488
|
-
|
|
9166
|
+
function createProviderCommand() {
|
|
9167
|
+
const cmd = new Command2("provider").description("Manage LLM provider configuration");
|
|
9168
|
+
cmd.command("config").description("Interactive provider configuration").action(async () => {
|
|
9169
|
+
const manager = getSettingsManager();
|
|
9170
|
+
const settings = manager.loadUserSettings();
|
|
9171
|
+
const providers = Object.keys(settings.providers);
|
|
9172
|
+
const { selectedProvider } = await inquirer.prompt([
|
|
9173
|
+
{
|
|
9174
|
+
type: "list",
|
|
9175
|
+
name: "selectedProvider",
|
|
9176
|
+
message: "Select a provider to configure:",
|
|
9177
|
+
choices: providers,
|
|
9178
|
+
default: settings.active_provider
|
|
9179
|
+
}
|
|
9180
|
+
]);
|
|
9181
|
+
const currentConfig = settings.providers[selectedProvider];
|
|
9182
|
+
if (!currentConfig) {
|
|
9183
|
+
console.error(chalk2.red(`Configuration for ${selectedProvider} not found.`));
|
|
9184
|
+
return;
|
|
9185
|
+
}
|
|
9186
|
+
const models = PROVIDER_MODELS[currentConfig.provider] || [];
|
|
9187
|
+
const { apiKey } = await inquirer.prompt([
|
|
9188
|
+
{
|
|
9189
|
+
type: "password",
|
|
9190
|
+
name: "apiKey",
|
|
9191
|
+
message: `Enter API Key for ${selectedProvider} (leave empty to keep current):`,
|
|
9192
|
+
mask: "*"
|
|
9193
|
+
}
|
|
9194
|
+
]);
|
|
9195
|
+
let selectedModel = currentConfig.model;
|
|
9196
|
+
if (models.length > 0) {
|
|
9197
|
+
const { model } = await inquirer.prompt([
|
|
9198
|
+
{
|
|
9199
|
+
type: "list",
|
|
9200
|
+
name: "model",
|
|
9201
|
+
message: "Select default model:",
|
|
9202
|
+
choices: [...models, "Custom..."],
|
|
9203
|
+
default: currentConfig.model
|
|
9204
|
+
}
|
|
9205
|
+
]);
|
|
9206
|
+
selectedModel = model;
|
|
9207
|
+
}
|
|
9208
|
+
if (selectedModel === "Custom..." || models.length === 0) {
|
|
9209
|
+
const { customModel } = await inquirer.prompt([
|
|
9210
|
+
{
|
|
9211
|
+
type: "input",
|
|
9212
|
+
name: "customModel",
|
|
9213
|
+
message: "Enter model ID:",
|
|
9214
|
+
default: currentConfig.model
|
|
9215
|
+
}
|
|
9216
|
+
]);
|
|
9217
|
+
selectedModel = customModel;
|
|
9218
|
+
}
|
|
9219
|
+
const { baseURL } = await inquirer.prompt([
|
|
9220
|
+
{
|
|
9221
|
+
type: "input",
|
|
9222
|
+
name: "baseURL",
|
|
9223
|
+
message: "Enter Base URL (optional, leave empty for default):",
|
|
9224
|
+
default: currentConfig.base_url
|
|
9225
|
+
}
|
|
9226
|
+
]);
|
|
9227
|
+
console.log(chalk2.blue(`
|
|
9228
|
+
New Configuration:`));
|
|
9229
|
+
console.log(`Provider: ${chalk2.bold(selectedProvider)}`);
|
|
9230
|
+
console.log(`Model: ${chalk2.bold(selectedModel)}`);
|
|
9231
|
+
console.log(`Base URL: ${baseURL || "Default"}`);
|
|
9232
|
+
const { confirm } = await inquirer.prompt([
|
|
9233
|
+
{
|
|
9234
|
+
type: "confirm",
|
|
9235
|
+
name: "confirm",
|
|
9236
|
+
message: "Save these settings?",
|
|
9237
|
+
default: true
|
|
9238
|
+
}
|
|
9239
|
+
]);
|
|
9240
|
+
if (confirm) {
|
|
9241
|
+
const newProviders = { ...settings.providers };
|
|
9242
|
+
newProviders[selectedProvider] = {
|
|
9243
|
+
...currentConfig,
|
|
9244
|
+
model: selectedModel,
|
|
9245
|
+
base_url: baseURL || currentConfig.base_url
|
|
9246
|
+
};
|
|
9247
|
+
if (apiKey) {
|
|
9248
|
+
newProviders[selectedProvider].api_key = apiKey;
|
|
9249
|
+
}
|
|
9250
|
+
if (baseURL !== undefined && baseURL !== currentConfig.base_url) {
|
|
9251
|
+
newProviders[selectedProvider].base_url = baseURL;
|
|
9252
|
+
}
|
|
9253
|
+
manager.updateUserSetting("providers", newProviders);
|
|
9254
|
+
if (settings.active_provider !== selectedProvider) {
|
|
9255
|
+
const { makeActive } = await inquirer.prompt([
|
|
9256
|
+
{
|
|
9257
|
+
type: "confirm",
|
|
9258
|
+
name: "makeActive",
|
|
9259
|
+
message: `Set ${selectedProvider} as active provider?`,
|
|
9260
|
+
default: true
|
|
9261
|
+
}
|
|
9262
|
+
]);
|
|
9263
|
+
if (makeActive) {
|
|
9264
|
+
manager.updateUserSetting("active_provider", selectedProvider);
|
|
9265
|
+
console.log(chalk2.green(`
|
|
9266
|
+
✅ Settings saved and ${selectedProvider} is now active.`));
|
|
9267
|
+
} else {
|
|
9268
|
+
console.log(chalk2.green(`
|
|
9269
|
+
✅ Settings saved.`));
|
|
9270
|
+
}
|
|
9271
|
+
} else {
|
|
9272
|
+
console.log(chalk2.green(`
|
|
9273
|
+
✅ Settings saved.`));
|
|
9274
|
+
}
|
|
9275
|
+
} else {
|
|
9276
|
+
console.log(chalk2.yellow("Configuration cancelled."));
|
|
9277
|
+
}
|
|
9278
|
+
});
|
|
9279
|
+
return cmd;
|
|
9280
|
+
}
|
|
9281
|
+
|
|
9282
|
+
// src/commands/index-cmd.ts
|
|
9283
|
+
import { Command as Command3 } from "commander";
|
|
9284
|
+
import fs18 from "fs/promises";
|
|
9285
|
+
import ignore from "ignore";
|
|
9286
|
+
import chalk3 from "chalk";
|
|
9287
|
+
import path17 from "path";
|
|
8489
9288
|
var DEFAULT_IGNORES = [
|
|
8490
9289
|
"node_modules",
|
|
8491
9290
|
".git",
|
|
@@ -8498,17 +9297,17 @@ var DEFAULT_IGNORES = [
|
|
|
8498
9297
|
"Thumbs.db"
|
|
8499
9298
|
];
|
|
8500
9299
|
function createIndexCommand() {
|
|
8501
|
-
const indexCommand = new
|
|
9300
|
+
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) => {
|
|
8502
9301
|
try {
|
|
8503
|
-
const rootDir =
|
|
8504
|
-
const outputFile2 = options.output ?
|
|
9302
|
+
const rootDir = path17.resolve(directory);
|
|
9303
|
+
const outputFile2 = options.output ? path17.resolve(options.output) : path17.join(rootDir, "index.md");
|
|
8505
9304
|
const maxDepth = parseInt(options.depth);
|
|
8506
|
-
console.log(
|
|
9305
|
+
console.log(chalk3.blue(`Indexing directory: ${rootDir}`));
|
|
8507
9306
|
const ig = ignore().add(DEFAULT_IGNORES);
|
|
8508
9307
|
if (options.ignore !== false) {
|
|
8509
9308
|
try {
|
|
8510
|
-
const gitignorePath =
|
|
8511
|
-
const gitignoreContent = await
|
|
9309
|
+
const gitignorePath = path17.join(rootDir, ".gitignore");
|
|
9310
|
+
const gitignoreContent = await fs18.readFile(gitignorePath, "utf-8");
|
|
8512
9311
|
ig.add(gitignoreContent);
|
|
8513
9312
|
} catch (e) {}
|
|
8514
9313
|
}
|
|
@@ -8523,19 +9322,19 @@ Date: ${new Date().toISOString()}
|
|
|
8523
9322
|
if (depth > maxDepth) {
|
|
8524
9323
|
return;
|
|
8525
9324
|
}
|
|
8526
|
-
const relativePath =
|
|
9325
|
+
const relativePath = path17.relative(rootDir, currentPath);
|
|
8527
9326
|
if (relativePath && ig.ignores(relativePath)) {
|
|
8528
9327
|
return;
|
|
8529
9328
|
}
|
|
8530
|
-
const stats = await
|
|
9329
|
+
const stats = await fs18.stat(currentPath);
|
|
8531
9330
|
const isDir = stats.isDirectory();
|
|
8532
|
-
const name =
|
|
9331
|
+
const name = path17.basename(currentPath);
|
|
8533
9332
|
if (isDir) {
|
|
8534
9333
|
if (relativePath) {
|
|
8535
9334
|
outputContent += `${prefix}${name}/
|
|
8536
9335
|
`;
|
|
8537
9336
|
}
|
|
8538
|
-
const entries = await
|
|
9337
|
+
const entries = await fs18.readdir(currentPath, {
|
|
8539
9338
|
withFileTypes: true
|
|
8540
9339
|
});
|
|
8541
9340
|
const sortedEntries = entries.sort((a, b) => {
|
|
@@ -8551,7 +9350,7 @@ Date: ${new Date().toISOString()}
|
|
|
8551
9350
|
const entry = sortedEntries[i];
|
|
8552
9351
|
const isLast = i === sortedEntries.length - 1;
|
|
8553
9352
|
const newPrefix = relativePath ? prefix + " " : "";
|
|
8554
|
-
await buildTree(
|
|
9353
|
+
await buildTree(path17.join(currentPath, entry.name), depth + 1, newPrefix);
|
|
8555
9354
|
}
|
|
8556
9355
|
} else {
|
|
8557
9356
|
outputContent += `${prefix}${name}
|
|
@@ -8563,10 +9362,10 @@ Date: ${new Date().toISOString()}
|
|
|
8563
9362
|
if (currentDepth > maxDepth) {
|
|
8564
9363
|
return;
|
|
8565
9364
|
}
|
|
8566
|
-
const entries = await
|
|
9365
|
+
const entries = await fs18.readdir(dir, { withFileTypes: true });
|
|
8567
9366
|
for (const entry of entries) {
|
|
8568
|
-
const fullPath =
|
|
8569
|
-
const relPath =
|
|
9367
|
+
const fullPath = path17.join(dir, entry.name);
|
|
9368
|
+
const relPath = path17.relative(rootDir, fullPath);
|
|
8570
9369
|
if (ig.ignores(relPath)) {
|
|
8571
9370
|
continue;
|
|
8572
9371
|
}
|
|
@@ -8578,8 +9377,8 @@ Date: ${new Date().toISOString()}
|
|
|
8578
9377
|
}
|
|
8579
9378
|
}
|
|
8580
9379
|
await walk(rootDir, 0);
|
|
8581
|
-
console.log(
|
|
8582
|
-
outputContent = `# Project Index: ${
|
|
9380
|
+
console.log(chalk3.blue(`Found ${files.length} files.`));
|
|
9381
|
+
outputContent = `# Project Index: ${path17.basename(rootDir)}
|
|
8583
9382
|
|
|
8584
9383
|
`;
|
|
8585
9384
|
outputContent += `Total Files: ${files.length}
|
|
@@ -8591,17 +9390,17 @@ Date: ${new Date().toISOString()}
|
|
|
8591
9390
|
for (const file of files) {
|
|
8592
9391
|
outputContent += `### ${file}
|
|
8593
9392
|
`;
|
|
8594
|
-
const stats = await
|
|
9393
|
+
const stats = await fs18.stat(path17.join(rootDir, file));
|
|
8595
9394
|
outputContent += `- Size: ${stats.size} bytes
|
|
8596
9395
|
`;
|
|
8597
9396
|
outputContent += `- Modified: ${stats.mtime.toISOString()}
|
|
8598
9397
|
|
|
8599
9398
|
`;
|
|
8600
9399
|
}
|
|
8601
|
-
await
|
|
8602
|
-
console.log(
|
|
9400
|
+
await fs18.writeFile(outputFile2, outputContent);
|
|
9401
|
+
console.log(chalk3.green(`✓ Index generated at: ${outputFile2}`));
|
|
8603
9402
|
} catch (error) {
|
|
8604
|
-
console.error(
|
|
9403
|
+
console.error(chalk3.red(`Error indexing directory: ${error.message}`));
|
|
8605
9404
|
process.exit(1);
|
|
8606
9405
|
}
|
|
8607
9406
|
});
|
|
@@ -8610,9 +9409,9 @@ Date: ${new Date().toISOString()}
|
|
|
8610
9409
|
|
|
8611
9410
|
// src/commands/plugins.ts
|
|
8612
9411
|
init_settings_manager();
|
|
8613
|
-
import { Command as
|
|
9412
|
+
import { Command as Command4 } from "commander";
|
|
8614
9413
|
function createPluginsCommand() {
|
|
8615
|
-
const pluginsCommand = new
|
|
9414
|
+
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");
|
|
8616
9415
|
pluginsCommand.command("list").description("List installed plugins").action(() => {
|
|
8617
9416
|
const manager = getSettingsManager();
|
|
8618
9417
|
const settings = manager.loadUserSettings();
|
|
@@ -8624,22 +9423,22 @@ function createPluginsCommand() {
|
|
|
8624
9423
|
console.log("Installed plugins:");
|
|
8625
9424
|
plugins.forEach((p) => console.log(`- ${p}`));
|
|
8626
9425
|
});
|
|
8627
|
-
pluginsCommand.command("install <path>").description("Install a plugin from a path, GitHub URL, or registry").action(async (
|
|
9426
|
+
pluginsCommand.command("install <path>").description("Install a plugin from a path, GitHub URL, or registry").action(async (path18) => {
|
|
8628
9427
|
try {
|
|
8629
9428
|
const manager = PluginManager.getInstance();
|
|
8630
|
-
console.log(`Installing plugin from: ${
|
|
8631
|
-
const installedPath = await manager.installPlugin(
|
|
9429
|
+
console.log(`Installing plugin from: ${path18}...`);
|
|
9430
|
+
const installedPath = await manager.installPlugin(path18);
|
|
8632
9431
|
console.log(`✅ Plugin installed successfully: ${installedPath}`);
|
|
8633
9432
|
} catch (error) {
|
|
8634
9433
|
console.error(`❌ Error installing plugin: ${error.message}`);
|
|
8635
9434
|
process.exit(1);
|
|
8636
9435
|
}
|
|
8637
9436
|
});
|
|
8638
|
-
pluginsCommand.command("uninstall <path>").description("Uninstall a plugin").action(async (
|
|
9437
|
+
pluginsCommand.command("uninstall <path>").description("Uninstall a plugin").action(async (path18) => {
|
|
8639
9438
|
try {
|
|
8640
9439
|
const manager = PluginManager.getInstance();
|
|
8641
|
-
await manager.removePlugin(
|
|
8642
|
-
console.log(`✅ Plugin uninstalled: ${
|
|
9440
|
+
await manager.removePlugin(path18);
|
|
9441
|
+
console.log(`✅ Plugin uninstalled: ${path18}`);
|
|
8643
9442
|
} catch (error) {
|
|
8644
9443
|
console.error(`❌ Error uninstalling plugin: ${error.message}`);
|
|
8645
9444
|
process.exit(1);
|
|
@@ -8650,109 +9449,12 @@ function createPluginsCommand() {
|
|
|
8650
9449
|
|
|
8651
9450
|
// src/commands/skills.ts
|
|
8652
9451
|
init_settings_manager();
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
import
|
|
8657
|
-
import path16 from "path";
|
|
8658
|
-
|
|
8659
|
-
class SkillsManager {
|
|
8660
|
-
static instance;
|
|
8661
|
-
skillsPath;
|
|
8662
|
-
constructor() {
|
|
8663
|
-
this.skillsPath = path16.join(getSettingsManager().getStorageDirectory(), "skills");
|
|
8664
|
-
}
|
|
8665
|
-
static getInstance() {
|
|
8666
|
-
if (!SkillsManager.instance) {
|
|
8667
|
-
SkillsManager.instance = new SkillsManager;
|
|
8668
|
-
}
|
|
8669
|
-
return SkillsManager.instance;
|
|
8670
|
-
}
|
|
8671
|
-
async ensureSkillsDirectory() {
|
|
8672
|
-
try {
|
|
8673
|
-
await fs17.mkdir(this.skillsPath, { recursive: true });
|
|
8674
|
-
} catch (error) {}
|
|
8675
|
-
}
|
|
8676
|
-
async listSkills() {
|
|
8677
|
-
await this.ensureSkillsDirectory();
|
|
8678
|
-
try {
|
|
8679
|
-
const files = await fs17.readdir(this.skillsPath);
|
|
8680
|
-
return files.filter((file) => file.endsWith(".ts") || file.endsWith(".js") || file.endsWith(".json")).map((file) => path16.parse(file).name);
|
|
8681
|
-
} catch (error) {
|
|
8682
|
-
return [];
|
|
8683
|
-
}
|
|
8684
|
-
}
|
|
8685
|
-
async getSkillPath(name) {
|
|
8686
|
-
const extensions = [".ts", ".js", ".json"];
|
|
8687
|
-
for (const ext of extensions) {
|
|
8688
|
-
const fullPath = path16.join(this.skillsPath, `${name}${ext}`);
|
|
8689
|
-
try {
|
|
8690
|
-
await fs17.access(fullPath);
|
|
8691
|
-
return fullPath;
|
|
8692
|
-
} catch {
|
|
8693
|
-
continue;
|
|
8694
|
-
}
|
|
8695
|
-
}
|
|
8696
|
-
throw new Error(`Skill '${name}' not found`);
|
|
8697
|
-
}
|
|
8698
|
-
async getSkillContent(name) {
|
|
8699
|
-
const skillPath = await this.getSkillPath(name);
|
|
8700
|
-
return await fs17.readFile(skillPath, "utf-8");
|
|
8701
|
-
}
|
|
8702
|
-
async createSkill(name, description, agent) {
|
|
8703
|
-
await this.ensureSkillsDirectory();
|
|
8704
|
-
const prompt = `Create a robust TypeScript skill for the Super Agent CLI named "${name}".
|
|
8705
|
-
|
|
8706
|
-
Description: ${description}
|
|
8707
|
-
|
|
8708
|
-
The skill should be a module that exports a default function or class that implements the desired functionality.
|
|
8709
|
-
It should valid standalone TypeScript code.
|
|
8710
|
-
Include comments explaining how it works.
|
|
8711
|
-
|
|
8712
|
-
Structure:
|
|
8713
|
-
\`\`\`typescript
|
|
8714
|
-
// ${name} skill
|
|
8715
|
-
export default async function(args: any) {
|
|
8716
|
-
// implementation
|
|
8717
|
-
}
|
|
8718
|
-
\`\`\`
|
|
8719
|
-
|
|
8720
|
-
Return ONLY the code block.`;
|
|
8721
|
-
const response = await agent.processUserMessage(prompt);
|
|
8722
|
-
let code = "";
|
|
8723
|
-
for (const entry of response) {
|
|
8724
|
-
if (entry.type === "assistant") {
|
|
8725
|
-
const match = entry.content.match(/```(?:typescript|ts)?\n([\s\S]*?)```/);
|
|
8726
|
-
if (match) {
|
|
8727
|
-
code = match[1];
|
|
8728
|
-
break;
|
|
8729
|
-
} else {
|
|
8730
|
-
code = entry.content;
|
|
8731
|
-
}
|
|
8732
|
-
}
|
|
8733
|
-
}
|
|
8734
|
-
if (!code) {
|
|
8735
|
-
throw new Error("Failed to generate skill code");
|
|
8736
|
-
}
|
|
8737
|
-
const filePath = path16.join(this.skillsPath, `${name}.ts`);
|
|
8738
|
-
await fs17.writeFile(filePath, code);
|
|
8739
|
-
}
|
|
8740
|
-
async deleteSkill(name) {
|
|
8741
|
-
try {
|
|
8742
|
-
const skillPath = await this.getSkillPath(name);
|
|
8743
|
-
await fs17.unlink(skillPath);
|
|
8744
|
-
} catch (error) {
|
|
8745
|
-
throw new Error(`Failed to delete skill '${name}': ${error.message}`);
|
|
8746
|
-
}
|
|
8747
|
-
}
|
|
8748
|
-
}
|
|
8749
|
-
|
|
8750
|
-
// src/commands/skills.ts
|
|
8751
|
-
import { Command as Command4 } from "commander";
|
|
8752
|
-
import inquirer from "inquirer";
|
|
8753
|
-
import chalk3 from "chalk";
|
|
9452
|
+
init_manager2();
|
|
9453
|
+
import { Command as Command5 } from "commander";
|
|
9454
|
+
import inquirer2 from "inquirer";
|
|
9455
|
+
import chalk4 from "chalk";
|
|
8754
9456
|
function createSkillsCommand() {
|
|
8755
|
-
const skillsCommand = new
|
|
9457
|
+
const skillsCommand = new Command5("skills").description("Manage AI skills");
|
|
8756
9458
|
skillsCommand.command("list").description("List available skills").action(async () => {
|
|
8757
9459
|
const manager = SkillsManager.getInstance();
|
|
8758
9460
|
const skills = await manager.listSkills();
|
|
@@ -8769,7 +9471,7 @@ function createSkillsCommand() {
|
|
|
8769
9471
|
const settingsManager = getSettingsManager();
|
|
8770
9472
|
let description = options.description;
|
|
8771
9473
|
if (!description) {
|
|
8772
|
-
const answer = await
|
|
9474
|
+
const answer = await inquirer2.prompt([
|
|
8773
9475
|
{
|
|
8774
9476
|
type: "input",
|
|
8775
9477
|
name: "description",
|
|
@@ -8778,146 +9480,136 @@ function createSkillsCommand() {
|
|
|
8778
9480
|
]);
|
|
8779
9481
|
description = answer.description;
|
|
8780
9482
|
}
|
|
8781
|
-
console.log(
|
|
9483
|
+
console.log(chalk4.blue(`Generating skill '${name}' based on description: "${description}"...`));
|
|
8782
9484
|
const apiKey = settingsManager.getApiKey();
|
|
8783
9485
|
const baseURL = settingsManager.getBaseURL();
|
|
8784
9486
|
const model = settingsManager.getCurrentModel();
|
|
8785
9487
|
if (!apiKey) {
|
|
8786
|
-
console.error(
|
|
9488
|
+
console.error(chalk4.red("API Key not found. Please configure it first."));
|
|
8787
9489
|
return;
|
|
8788
9490
|
}
|
|
8789
9491
|
const agent = new SuperAgent(apiKey, baseURL, model);
|
|
8790
9492
|
await manager.createSkill(name, description, agent);
|
|
8791
|
-
console.log(
|
|
9493
|
+
console.log(chalk4.green(`✓ Skill '${name}' created successfully.`));
|
|
8792
9494
|
} catch (error) {
|
|
8793
|
-
console.error(
|
|
9495
|
+
console.error(chalk4.red(`Error creating skill: ${error.message}`));
|
|
8794
9496
|
}
|
|
8795
9497
|
});
|
|
8796
9498
|
skillsCommand.command("delete <name>").description("Delete a skill").action(async (name) => {
|
|
8797
9499
|
try {
|
|
8798
9500
|
const manager = SkillsManager.getInstance();
|
|
8799
9501
|
await manager.deleteSkill(name);
|
|
8800
|
-
console.log(
|
|
9502
|
+
console.log(chalk4.green(`✓ Skill '${name}' deleted.`));
|
|
8801
9503
|
} catch (error) {
|
|
8802
|
-
console.error(
|
|
9504
|
+
console.error(chalk4.red(`Error deleting skill: ${error.message}`));
|
|
8803
9505
|
}
|
|
8804
9506
|
});
|
|
8805
9507
|
return skillsCommand;
|
|
8806
9508
|
}
|
|
8807
9509
|
|
|
8808
|
-
// src/commands/
|
|
8809
|
-
init_settings_manager();
|
|
8810
|
-
|
|
8811
|
-
// src/agents/manager.ts
|
|
9510
|
+
// src/commands/import.ts
|
|
8812
9511
|
init_settings_manager();
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
9512
|
+
init_file_utils();
|
|
9513
|
+
init_manager2();
|
|
9514
|
+
init_manager();
|
|
9515
|
+
import { Command as Command6 } from "commander";
|
|
9516
|
+
import fs19 from "fs-extra";
|
|
9517
|
+
import chalk5 from "chalk";
|
|
9518
|
+
import path18 from "path";
|
|
9519
|
+
function createImportCommand() {
|
|
9520
|
+
const cmd = new Command6("import").description("Import resources from other AI assistants");
|
|
9521
|
+
cmd.command("agents <source>").description("Import agents from source (gemini, claude, kilo)").action(async (source) => {
|
|
9522
|
+
const sourcePath = resolveSourcePath(source);
|
|
9523
|
+
const agentsDir = path18.join(sourcePath, "agents");
|
|
9524
|
+
if (!await fs19.pathExists(agentsDir)) {
|
|
9525
|
+
console.error(chalk5.red(`Agents directory not found at ${agentsDir}`));
|
|
9526
|
+
return;
|
|
8825
9527
|
}
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
|
|
8836
|
-
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
9528
|
+
const files = await fs19.readdir(agentsDir);
|
|
9529
|
+
const manager = AgentsManager.getInstance();
|
|
9530
|
+
let count = 0;
|
|
9531
|
+
for (const file of files) {
|
|
9532
|
+
if (file.endsWith(".json")) {
|
|
9533
|
+
try {
|
|
9534
|
+
const content = await fs19.readJson(path18.join(agentsDir, file));
|
|
9535
|
+
const agentConfig = {
|
|
9536
|
+
name: content.name || path18.parse(file).name,
|
|
9537
|
+
role: content.role || "Assistant",
|
|
9538
|
+
description: content.description || "Imported agent",
|
|
9539
|
+
model: content.model,
|
|
9540
|
+
tools: content.tools,
|
|
9541
|
+
temperature: content.temperature,
|
|
9542
|
+
systemPrompt: content.systemPrompt || content.system_prompt || content.prompt
|
|
9543
|
+
};
|
|
9544
|
+
await manager.createAgent(agentConfig);
|
|
9545
|
+
console.log(chalk5.green(`Imported agent: ${agentConfig.name}`));
|
|
9546
|
+
count++;
|
|
9547
|
+
} catch (error) {
|
|
9548
|
+
console.warn(chalk5.yellow(`Failed to import ${file}: ${error.message}`));
|
|
8844
9549
|
}
|
|
8845
9550
|
}
|
|
8846
|
-
return agents;
|
|
8847
|
-
} catch (error) {
|
|
8848
|
-
return [];
|
|
8849
|
-
}
|
|
8850
|
-
}
|
|
8851
|
-
async getAgent(name) {
|
|
8852
|
-
try {
|
|
8853
|
-
const content = await fs18.readFile(path17.join(this.agentsPath, `${name}.json`), "utf-8");
|
|
8854
|
-
return JSON.parse(content);
|
|
8855
|
-
} catch (error) {
|
|
8856
|
-
return null;
|
|
8857
9551
|
}
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
|
|
8861
|
-
const
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
The configuration should be a JSON object matching this interface:
|
|
8868
|
-
interface AgentConfig {
|
|
8869
|
-
name: string;
|
|
8870
|
-
role: string;
|
|
8871
|
-
description: string;
|
|
8872
|
-
model?: string; // suggest a model if appropriate, or leave undefined
|
|
8873
|
-
tools?: string[]; // suggest relevant tools/skills names
|
|
8874
|
-
temperature?: number;
|
|
8875
|
-
systemPrompt?: string; // a detailed system prompt for this agent
|
|
9552
|
+
console.log(chalk5.bold(`Imported ${count} agents.`));
|
|
9553
|
+
});
|
|
9554
|
+
cmd.command("skills <source>").description("Import skills from source (gemini, claude, kilo)").action(async (source) => {
|
|
9555
|
+
const sourcePath = resolveSourcePath(source);
|
|
9556
|
+
const skillsDir = path18.join(sourcePath, "skills");
|
|
9557
|
+
if (!await fs19.pathExists(skillsDir)) {
|
|
9558
|
+
console.error(chalk5.red(`Skills directory not found at ${skillsDir}`));
|
|
9559
|
+
return;
|
|
8876
9560
|
}
|
|
8877
|
-
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
|
|
8884
|
-
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
|
|
8890
|
-
}
|
|
9561
|
+
const files = await fs19.readdir(skillsDir);
|
|
9562
|
+
const manager = SkillsManager.getInstance();
|
|
9563
|
+
let count = 0;
|
|
9564
|
+
for (const file of files) {
|
|
9565
|
+
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
9566
|
+
try {
|
|
9567
|
+
const content = await fs19.readFile(path18.join(skillsDir, file), "utf-8");
|
|
9568
|
+
const name = path18.parse(file).name;
|
|
9569
|
+
await manager.saveSkill(name, content);
|
|
9570
|
+
console.log(chalk5.green(`Imported skill: ${name}`));
|
|
9571
|
+
count++;
|
|
9572
|
+
} catch (error) {
|
|
9573
|
+
console.warn(chalk5.yellow(`Failed to import ${file}: ${error.message}`));
|
|
8891
9574
|
}
|
|
8892
9575
|
}
|
|
8893
9576
|
}
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
9577
|
+
console.log(chalk5.bold(`Imported ${count} skills.`));
|
|
9578
|
+
});
|
|
9579
|
+
cmd.command("hooks <source>").description("Import hooks from source settings").action(async (source) => {
|
|
9580
|
+
const sourcePath = resolveSourcePath(source);
|
|
9581
|
+
const settingsFile = source.toLowerCase() === "claude" ? "settings.local.json" : "settings.json";
|
|
9582
|
+
const fullPath = path18.join(sourcePath, settingsFile);
|
|
9583
|
+
if (!await fs19.pathExists(fullPath)) {
|
|
9584
|
+
console.error(chalk5.red(`Settings file not found at ${fullPath}`));
|
|
9585
|
+
return;
|
|
8903
9586
|
}
|
|
8904
|
-
}
|
|
8905
|
-
async deleteAgent(name) {
|
|
8906
9587
|
try {
|
|
8907
|
-
const
|
|
8908
|
-
|
|
9588
|
+
const settings = await fs19.readJson(fullPath);
|
|
9589
|
+
if (settings.hooks) {
|
|
9590
|
+
const manager = getSettingsManager();
|
|
9591
|
+
const currentHooks = manager.getUserSetting("hooks") || {};
|
|
9592
|
+
const mergedHooks = { ...currentHooks, ...settings.hooks };
|
|
9593
|
+
manager.updateUserSetting("hooks", mergedHooks);
|
|
9594
|
+
console.log(chalk5.green(`Imported ${Object.keys(settings.hooks).length} hooks.`));
|
|
9595
|
+
} else {
|
|
9596
|
+
console.log(chalk5.yellow("No hooks found in settings file."));
|
|
9597
|
+
}
|
|
8909
9598
|
} catch (error) {
|
|
8910
|
-
|
|
9599
|
+
console.error(chalk5.red(`Failed to import hooks: ${error.message}`));
|
|
8911
9600
|
}
|
|
8912
|
-
}
|
|
9601
|
+
});
|
|
9602
|
+
return cmd;
|
|
8913
9603
|
}
|
|
8914
9604
|
|
|
8915
9605
|
// src/commands/agents.ts
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
import
|
|
9606
|
+
init_settings_manager();
|
|
9607
|
+
init_manager();
|
|
9608
|
+
import { Command as Command7 } from "commander";
|
|
9609
|
+
import inquirer3 from "inquirer";
|
|
9610
|
+
import chalk6 from "chalk";
|
|
8919
9611
|
function createAgentsCommand() {
|
|
8920
|
-
const agentsCommand = new
|
|
9612
|
+
const agentsCommand = new Command7("agents").description("Manage AI agents");
|
|
8921
9613
|
agentsCommand.command("list").description("List available agents").action(async () => {
|
|
8922
9614
|
const manager = AgentsManager.getInstance();
|
|
8923
9615
|
const agents = await manager.listAgents();
|
|
@@ -8926,8 +9618,8 @@ function createAgentsCommand() {
|
|
|
8926
9618
|
} else {
|
|
8927
9619
|
console.log("Available agents:");
|
|
8928
9620
|
agents.forEach((agent) => {
|
|
8929
|
-
console.log(`- ${
|
|
8930
|
-
console.log(` ${
|
|
9621
|
+
console.log(`- ${chalk6.bold(agent.name)} (${agent.role})`);
|
|
9622
|
+
console.log(` ${chalk6.dim(agent.description)}`);
|
|
8931
9623
|
});
|
|
8932
9624
|
}
|
|
8933
9625
|
});
|
|
@@ -8937,7 +9629,7 @@ function createAgentsCommand() {
|
|
|
8937
9629
|
const settingsManager = getSettingsManager();
|
|
8938
9630
|
let description = options.description;
|
|
8939
9631
|
if (!description) {
|
|
8940
|
-
const answer = await
|
|
9632
|
+
const answer = await inquirer3.prompt([
|
|
8941
9633
|
{
|
|
8942
9634
|
type: "input",
|
|
8943
9635
|
name: "description",
|
|
@@ -8946,28 +9638,28 @@ function createAgentsCommand() {
|
|
|
8946
9638
|
]);
|
|
8947
9639
|
description = answer.description;
|
|
8948
9640
|
}
|
|
8949
|
-
console.log(
|
|
9641
|
+
console.log(chalk6.blue(`Generating agent configuration for '${name}'...`));
|
|
8950
9642
|
const apiKey = settingsManager.getApiKey();
|
|
8951
9643
|
const baseURL = settingsManager.getBaseURL();
|
|
8952
9644
|
const model = settingsManager.getCurrentModel();
|
|
8953
9645
|
if (!apiKey) {
|
|
8954
|
-
console.error(
|
|
9646
|
+
console.error(chalk6.red("API Key not found. Please configure it first."));
|
|
8955
9647
|
return;
|
|
8956
9648
|
}
|
|
8957
9649
|
const agent = new SuperAgent(apiKey, baseURL, model);
|
|
8958
9650
|
await manager.generateAgent(name, description, agent);
|
|
8959
|
-
console.log(
|
|
9651
|
+
console.log(chalk6.green(`✓ Agent '${name}' created successfully.`));
|
|
8960
9652
|
} catch (error) {
|
|
8961
|
-
console.error(
|
|
9653
|
+
console.error(chalk6.red(`Error creating agent: ${error.message}`));
|
|
8962
9654
|
}
|
|
8963
9655
|
});
|
|
8964
9656
|
agentsCommand.command("delete <name>").description("Delete an agent").action(async (name) => {
|
|
8965
9657
|
try {
|
|
8966
9658
|
const manager = AgentsManager.getInstance();
|
|
8967
9659
|
await manager.deleteAgent(name);
|
|
8968
|
-
console.log(
|
|
9660
|
+
console.log(chalk6.green(`✓ Agent '${name}' deleted.`));
|
|
8969
9661
|
} catch (error) {
|
|
8970
|
-
console.error(
|
|
9662
|
+
console.error(chalk6.red(`Error deleting agent: ${error.message}`));
|
|
8971
9663
|
}
|
|
8972
9664
|
});
|
|
8973
9665
|
return agentsCommand;
|
|
@@ -8975,37 +9667,37 @@ function createAgentsCommand() {
|
|
|
8975
9667
|
|
|
8976
9668
|
// src/commands/mcp.ts
|
|
8977
9669
|
init_config();
|
|
8978
|
-
import { Command as
|
|
8979
|
-
import
|
|
9670
|
+
import { Command as Command8 } from "commander";
|
|
9671
|
+
import chalk7 from "chalk";
|
|
8980
9672
|
function createMCPCommand() {
|
|
8981
|
-
const mcpCommand = new
|
|
9673
|
+
const mcpCommand = new Command8("mcp");
|
|
8982
9674
|
mcpCommand.description("Manage MCP (Model Context Protocol) servers");
|
|
8983
9675
|
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) => {
|
|
8984
9676
|
try {
|
|
8985
9677
|
if (PREDEFINED_SERVERS[name]) {
|
|
8986
9678
|
const config2 = PREDEFINED_SERVERS[name];
|
|
8987
9679
|
addMCPServer(config2);
|
|
8988
|
-
console.log(
|
|
9680
|
+
console.log(chalk7.green(`✓ Added predefined MCP server: ${name}`));
|
|
8989
9681
|
const manager2 = getMCPManager();
|
|
8990
9682
|
await manager2.addServer(config2);
|
|
8991
|
-
console.log(
|
|
9683
|
+
console.log(chalk7.green(`✓ Connected to MCP server: ${name}`));
|
|
8992
9684
|
const tools2 = manager2.getTools().filter((t) => t.serverName === name);
|
|
8993
|
-
console.log(
|
|
9685
|
+
console.log(chalk7.blue(` Available tools: ${tools2.length}`));
|
|
8994
9686
|
return;
|
|
8995
9687
|
}
|
|
8996
9688
|
const transportType = options.transport.toLowerCase();
|
|
8997
9689
|
if (transportType === "stdio") {
|
|
8998
9690
|
if (!options.command) {
|
|
8999
|
-
console.error(
|
|
9691
|
+
console.error(chalk7.red("Error: --command is required for stdio transport"));
|
|
9000
9692
|
process.exit(1);
|
|
9001
9693
|
}
|
|
9002
9694
|
} else if (transportType === "http" || transportType === "sse" || transportType === "streamable_http") {
|
|
9003
9695
|
if (!options.url) {
|
|
9004
|
-
console.error(
|
|
9696
|
+
console.error(chalk7.red(`Error: --url is required for ${transportType} transport`));
|
|
9005
9697
|
process.exit(1);
|
|
9006
9698
|
}
|
|
9007
9699
|
} else {
|
|
9008
|
-
console.error(
|
|
9700
|
+
console.error(chalk7.red("Error: Transport type must be stdio, http, sse, or streamable_http"));
|
|
9009
9701
|
process.exit(1);
|
|
9010
9702
|
}
|
|
9011
9703
|
const env = {};
|
|
@@ -9034,14 +9726,14 @@ function createMCPCommand() {
|
|
|
9034
9726
|
}
|
|
9035
9727
|
};
|
|
9036
9728
|
addMCPServer(config);
|
|
9037
|
-
console.log(
|
|
9729
|
+
console.log(chalk7.green(`✓ Added MCP server: ${name}`));
|
|
9038
9730
|
const manager = getMCPManager();
|
|
9039
9731
|
await manager.addServer(config);
|
|
9040
|
-
console.log(
|
|
9732
|
+
console.log(chalk7.green(`✓ Connected to MCP server: ${name}`));
|
|
9041
9733
|
const tools = manager.getTools().filter((t) => t.serverName === name);
|
|
9042
|
-
console.log(
|
|
9734
|
+
console.log(chalk7.blue(` Available tools: ${tools.length}`));
|
|
9043
9735
|
} catch (error) {
|
|
9044
|
-
console.error(
|
|
9736
|
+
console.error(chalk7.red(`Error adding MCP server: ${error.message}`));
|
|
9045
9737
|
process.exit(1);
|
|
9046
9738
|
}
|
|
9047
9739
|
});
|
|
@@ -9051,7 +9743,7 @@ function createMCPCommand() {
|
|
|
9051
9743
|
try {
|
|
9052
9744
|
config = JSON.parse(jsonConfig);
|
|
9053
9745
|
} catch (error) {
|
|
9054
|
-
console.error(
|
|
9746
|
+
console.error(chalk7.red("Error: Invalid JSON configuration"));
|
|
9055
9747
|
process.exit(1);
|
|
9056
9748
|
}
|
|
9057
9749
|
const serverConfig = {
|
|
@@ -9076,14 +9768,14 @@ function createMCPCommand() {
|
|
|
9076
9768
|
}
|
|
9077
9769
|
}
|
|
9078
9770
|
addMCPServer(serverConfig);
|
|
9079
|
-
console.log(
|
|
9771
|
+
console.log(chalk7.green(`✓ Added MCP server: ${name}`));
|
|
9080
9772
|
const manager = getMCPManager();
|
|
9081
9773
|
await manager.addServer(serverConfig);
|
|
9082
|
-
console.log(
|
|
9774
|
+
console.log(chalk7.green(`✓ Connected to MCP server: ${name}`));
|
|
9083
9775
|
const tools = manager.getTools().filter((t) => t.serverName === name);
|
|
9084
|
-
console.log(
|
|
9776
|
+
console.log(chalk7.blue(` Available tools: ${tools.length}`));
|
|
9085
9777
|
} catch (error) {
|
|
9086
|
-
console.error(
|
|
9778
|
+
console.error(chalk7.red(`Error adding MCP server: ${error.message}`));
|
|
9087
9779
|
process.exit(1);
|
|
9088
9780
|
}
|
|
9089
9781
|
});
|
|
@@ -9092,9 +9784,9 @@ function createMCPCommand() {
|
|
|
9092
9784
|
const manager = getMCPManager();
|
|
9093
9785
|
await manager.removeServer(name);
|
|
9094
9786
|
removeMCPServer(name);
|
|
9095
|
-
console.log(
|
|
9787
|
+
console.log(chalk7.green(`✓ Removed MCP server: ${name}`));
|
|
9096
9788
|
} catch (error) {
|
|
9097
|
-
console.error(
|
|
9789
|
+
console.error(chalk7.red(`Error removing MCP server: ${error.message}`));
|
|
9098
9790
|
process.exit(1);
|
|
9099
9791
|
}
|
|
9100
9792
|
});
|
|
@@ -9102,15 +9794,15 @@ function createMCPCommand() {
|
|
|
9102
9794
|
const config = loadMCPConfig();
|
|
9103
9795
|
const manager = getMCPManager();
|
|
9104
9796
|
if (config.servers.length === 0) {
|
|
9105
|
-
console.log(
|
|
9797
|
+
console.log(chalk7.yellow("No MCP servers configured"));
|
|
9106
9798
|
return;
|
|
9107
9799
|
}
|
|
9108
|
-
console.log(
|
|
9800
|
+
console.log(chalk7.bold("Configured MCP servers:"));
|
|
9109
9801
|
console.log();
|
|
9110
9802
|
for (const server of config.servers) {
|
|
9111
9803
|
const isConnected = manager.getServers().includes(server.name);
|
|
9112
|
-
const status = isConnected ?
|
|
9113
|
-
console.log(`${
|
|
9804
|
+
const status = isConnected ? chalk7.green("✓ Connected") : chalk7.red("✗ Disconnected");
|
|
9805
|
+
console.log(`${chalk7.bold(server.name)}: ${status}`);
|
|
9114
9806
|
if (server.transport) {
|
|
9115
9807
|
console.log(` Transport: ${server.transport.type}`);
|
|
9116
9808
|
if (server.transport.type === "stdio") {
|
|
@@ -9143,15 +9835,15 @@ function createMCPCommand() {
|
|
|
9143
9835
|
const config = loadMCPConfig();
|
|
9144
9836
|
const serverConfig = config.servers.find((s) => s.name === name);
|
|
9145
9837
|
if (!serverConfig) {
|
|
9146
|
-
console.error(
|
|
9838
|
+
console.error(chalk7.red(`Server ${name} not found`));
|
|
9147
9839
|
process.exit(1);
|
|
9148
9840
|
}
|
|
9149
|
-
console.log(
|
|
9841
|
+
console.log(chalk7.blue(`Testing connection to ${name}...`));
|
|
9150
9842
|
const manager = getMCPManager();
|
|
9151
9843
|
await manager.addServer(serverConfig);
|
|
9152
9844
|
const tools = manager.getTools().filter((t) => t.serverName === name);
|
|
9153
|
-
console.log(
|
|
9154
|
-
console.log(
|
|
9845
|
+
console.log(chalk7.green(`✓ Successfully connected to ${name}`));
|
|
9846
|
+
console.log(chalk7.blue(` Available tools: ${tools.length}`));
|
|
9155
9847
|
if (tools.length > 0) {
|
|
9156
9848
|
console.log(" Tools:");
|
|
9157
9849
|
tools.forEach((tool) => {
|
|
@@ -9160,7 +9852,7 @@ function createMCPCommand() {
|
|
|
9160
9852
|
});
|
|
9161
9853
|
}
|
|
9162
9854
|
} catch (error) {
|
|
9163
|
-
console.error(
|
|
9855
|
+
console.error(chalk7.red(`✗ Failed to connect to ${name}: ${error.message}`));
|
|
9164
9856
|
process.exit(1);
|
|
9165
9857
|
}
|
|
9166
9858
|
});
|
|
@@ -9169,7 +9861,7 @@ function createMCPCommand() {
|
|
|
9169
9861
|
|
|
9170
9862
|
// src/commands/git.ts
|
|
9171
9863
|
init_settings_manager();
|
|
9172
|
-
import { Command as
|
|
9864
|
+
import { Command as Command9 } from "commander";
|
|
9173
9865
|
async function loadApiKey() {
|
|
9174
9866
|
const manager = getSettingsManager();
|
|
9175
9867
|
return manager.getApiKey();
|
|
@@ -9273,7 +9965,7 @@ Respond with ONLY the commit message, no additional text.`;
|
|
|
9273
9965
|
}
|
|
9274
9966
|
}
|
|
9275
9967
|
function createGitCommand() {
|
|
9276
|
-
const gitCommand = new
|
|
9968
|
+
const gitCommand = new Command9("git").description("Git operations with AI assistance");
|
|
9277
9969
|
gitCommand.command("commit-and-push").description("Generate AI commit message and push to remote").option("-d, --directory <dir>", "set working directory", process.cwd()).option("-k, --api-key <key>", "Super Agent API key (or set SUPER_AGENT_API_KEY env var)").option("-u, --base-url <url>", "Super Agent API base URL (or set SUPER_AGENT_BASE_URL env var)").option("-m, --model <model>", "AI model to use (e.g., GLM-4.7) (or set SUPER_AGENT_MODEL env var)").option("--max-tool-rounds <rounds>", "maximum number of tool execution rounds (default: 400)", "400").action(async (options) => {
|
|
9278
9970
|
if (options.directory) {
|
|
9279
9971
|
try {
|
|
@@ -9313,6 +10005,8 @@ function registerCommands(program) {
|
|
|
9313
10005
|
program.addCommand(createServeCommand());
|
|
9314
10006
|
program.addCommand(createSkillsCommand());
|
|
9315
10007
|
program.addCommand(createAgentsCommand());
|
|
10008
|
+
program.addCommand(createImportCommand());
|
|
10009
|
+
program.addCommand(createProviderCommand());
|
|
9316
10010
|
program.addCommand(createIndexCommand());
|
|
9317
10011
|
}
|
|
9318
10012
|
|