thanh-kit 2.5.8 → 2.5.10
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 +397 -315
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/codex/config.toml +8 -0
- package/templates/gemini/settings.json +37 -0
- package/templates/settings.local.json +1 -14
package/dist/index.js
CHANGED
|
@@ -582,7 +582,7 @@ var init_claude_adapter = __esm({
|
|
|
582
582
|
|
|
583
583
|
// src/targets/gemini-adapter.ts
|
|
584
584
|
import fs3 from "fs-extra";
|
|
585
|
-
import { join as join4
|
|
585
|
+
import { join as join4 } from "path";
|
|
586
586
|
function parseFrontmatter(content) {
|
|
587
587
|
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
588
588
|
if (!match) {
|
|
@@ -590,9 +590,6 @@ function parseFrontmatter(content) {
|
|
|
590
590
|
}
|
|
591
591
|
return { frontmatter: match[1], body: match[2] };
|
|
592
592
|
}
|
|
593
|
-
function escapeTomlString(str) {
|
|
594
|
-
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\t/g, "\\t");
|
|
595
|
-
}
|
|
596
593
|
function convertAgentToGemini(mdContent) {
|
|
597
594
|
const { frontmatter, body } = parseFrontmatter(mdContent);
|
|
598
595
|
if (!frontmatter) return mdContent;
|
|
@@ -614,20 +611,6 @@ ${converted.trim()}
|
|
|
614
611
|
---
|
|
615
612
|
${body}`;
|
|
616
613
|
}
|
|
617
|
-
function convertCommandToToml(mdContent) {
|
|
618
|
-
const { frontmatter, body } = parseFrontmatter(mdContent);
|
|
619
|
-
const descMatch = frontmatter.match(/description:\s*(.+)/);
|
|
620
|
-
const description = descMatch ? descMatch[1].trim() : "";
|
|
621
|
-
const prompt = body.trim().replace(/\$ARGUMENTS/g, "{{args}}");
|
|
622
|
-
const lines = [];
|
|
623
|
-
if (description) {
|
|
624
|
-
lines.push(`description = "${escapeTomlString(description)}"`);
|
|
625
|
-
}
|
|
626
|
-
lines.push(`prompt = '''
|
|
627
|
-
${prompt}
|
|
628
|
-
'''`);
|
|
629
|
-
return lines.join("\n");
|
|
630
|
-
}
|
|
631
614
|
var MODEL_MAP, GeminiAdapter;
|
|
632
615
|
var init_gemini_adapter = __esm({
|
|
633
616
|
"src/targets/gemini-adapter.ts"() {
|
|
@@ -648,7 +631,8 @@ var init_gemini_adapter = __esm({
|
|
|
648
631
|
features: {
|
|
649
632
|
agents: true,
|
|
650
633
|
skills: true,
|
|
651
|
-
commands:
|
|
634
|
+
commands: false,
|
|
635
|
+
// Gemini uses skills, not commands
|
|
652
636
|
workflows: false,
|
|
653
637
|
router: false,
|
|
654
638
|
hooks: false,
|
|
@@ -740,88 +724,183 @@ var init_gemini_adapter = __esm({
|
|
|
740
724
|
}
|
|
741
725
|
return { copied, skipped, errors };
|
|
742
726
|
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
727
|
+
// Commands not supported - Gemini uses skills instead
|
|
728
|
+
async copyCommands(_items, _sourceDir, _targetDir, _mergeMode) {
|
|
729
|
+
return { copied: [], skipped: [], errors: [] };
|
|
730
|
+
}
|
|
731
|
+
async copyBaseFiles(targetDir, mergeMode) {
|
|
732
|
+
const { CLI_ROOT: CLI_ROOT2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
733
|
+
const geminiTemplates = join4(CLI_ROOT2, "templates", "gemini");
|
|
734
|
+
const copied = [];
|
|
735
|
+
const settingsPath = join4(geminiTemplates, "settings.json");
|
|
736
|
+
const destSettingsPath = join4(targetDir, "settings.json");
|
|
737
|
+
if (fs3.existsSync(settingsPath)) {
|
|
738
|
+
if (!(mergeMode && fs3.existsSync(destSettingsPath))) {
|
|
739
|
+
await fs3.copy(settingsPath, destSettingsPath, { overwrite: !mergeMode });
|
|
740
|
+
copied.push("settings.json");
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
return copied;
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
// src/targets/codex-adapter.ts
|
|
750
|
+
import fs4 from "fs-extra";
|
|
751
|
+
import { join as join5 } from "path";
|
|
752
|
+
function parseFrontmatter2(content) {
|
|
753
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
754
|
+
if (!match) {
|
|
755
|
+
return { frontmatter: "", body: content };
|
|
756
|
+
}
|
|
757
|
+
return { frontmatter: match[1], body: match[2] };
|
|
758
|
+
}
|
|
759
|
+
function convertAgentToCodex(mdContent) {
|
|
760
|
+
const { frontmatter, body } = parseFrontmatter2(mdContent);
|
|
761
|
+
if (!frontmatter) return mdContent;
|
|
762
|
+
let converted = frontmatter;
|
|
763
|
+
for (const [claudeModel, codexModel] of Object.entries(MODEL_MAP2)) {
|
|
764
|
+
const regex = new RegExp(`^model:\\s*${claudeModel}\\s*$`, "m");
|
|
765
|
+
if (codexModel) {
|
|
766
|
+
converted = converted.replace(regex, `model: ${codexModel}`);
|
|
767
|
+
} else {
|
|
768
|
+
converted = converted.replace(regex, "");
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
converted = converted.replace(/^tools:\s*.+$/m, "");
|
|
772
|
+
return `---
|
|
773
|
+
${converted.trim()}
|
|
774
|
+
---
|
|
775
|
+
${body}`;
|
|
776
|
+
}
|
|
777
|
+
var MODEL_MAP2, CodexAdapter;
|
|
778
|
+
var init_codex_adapter = __esm({
|
|
779
|
+
"src/targets/codex-adapter.ts"() {
|
|
780
|
+
"use strict";
|
|
781
|
+
init_base_adapter();
|
|
782
|
+
MODEL_MAP2 = {
|
|
783
|
+
"opus": "o3",
|
|
784
|
+
"sonnet": "o4-mini",
|
|
785
|
+
"haiku": "gpt-4.1-mini",
|
|
786
|
+
"inherit": ""
|
|
787
|
+
// Remove inherit, let Codex use default
|
|
788
|
+
};
|
|
789
|
+
CodexAdapter = class extends BaseTargetAdapter {
|
|
790
|
+
config = {
|
|
791
|
+
name: "codex",
|
|
792
|
+
displayName: "Codex CLI",
|
|
793
|
+
directory: ".agents",
|
|
794
|
+
features: {
|
|
795
|
+
agents: true,
|
|
796
|
+
skills: true,
|
|
797
|
+
commands: false,
|
|
798
|
+
// Codex uses skills, not commands
|
|
799
|
+
workflows: false,
|
|
800
|
+
router: false,
|
|
801
|
+
hooks: false,
|
|
802
|
+
memory: false,
|
|
803
|
+
scripts: false,
|
|
804
|
+
"output-styles": false
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
async copyAgents(items, sourceDir, targetDir, mergeMode) {
|
|
808
|
+
const typeDir = join5(sourceDir, "agents");
|
|
809
|
+
const destTypeDir = join5(targetDir, "agents");
|
|
810
|
+
if (!fs4.existsSync(typeDir)) {
|
|
747
811
|
return { copied: [], skipped: [], errors: [] };
|
|
748
812
|
}
|
|
749
|
-
await
|
|
750
|
-
let
|
|
813
|
+
await fs4.ensureDir(destTypeDir);
|
|
814
|
+
let agentList;
|
|
751
815
|
if (items === "all") {
|
|
752
|
-
const entries =
|
|
753
|
-
|
|
816
|
+
const entries = fs4.readdirSync(typeDir);
|
|
817
|
+
agentList = entries.filter((e) => e.endsWith(".md") && e !== "README.md").map((e) => e.replace(".md", ""));
|
|
754
818
|
} else {
|
|
755
|
-
|
|
819
|
+
agentList = items;
|
|
756
820
|
}
|
|
757
821
|
const copied = [];
|
|
758
822
|
const skipped = [];
|
|
759
823
|
const errors = [];
|
|
760
|
-
for (const
|
|
824
|
+
for (const agent of agentList) {
|
|
761
825
|
try {
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
const destPath = join4(destTypeDir, item + ".toml");
|
|
767
|
-
if (!(mergeMode && fs3.existsSync(destPath))) {
|
|
768
|
-
await fs3.ensureDir(dirname3(destPath));
|
|
769
|
-
const mdContent = fs3.readFileSync(srcPathMd, "utf-8");
|
|
770
|
-
const tomlContent = convertCommandToToml(mdContent);
|
|
771
|
-
await fs3.writeFile(destPath, tomlContent, "utf-8");
|
|
772
|
-
copiedSomething = true;
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
if (fs3.existsSync(srcPathDir) && fs3.statSync(srcPathDir).isDirectory()) {
|
|
776
|
-
await this.convertDirectoryToToml(srcPathDir, join4(destTypeDir, item), mergeMode);
|
|
777
|
-
copiedSomething = true;
|
|
826
|
+
const srcPath = join5(typeDir, agent + ".md");
|
|
827
|
+
if (!fs4.existsSync(srcPath)) {
|
|
828
|
+
skipped.push(agent);
|
|
829
|
+
continue;
|
|
778
830
|
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
831
|
+
const destPath = join5(destTypeDir, agent + ".md");
|
|
832
|
+
if (mergeMode && fs4.existsSync(destPath)) {
|
|
833
|
+
skipped.push(agent);
|
|
834
|
+
continue;
|
|
783
835
|
}
|
|
836
|
+
const mdContent = fs4.readFileSync(srcPath, "utf-8");
|
|
837
|
+
const convertedContent = convertAgentToCodex(mdContent);
|
|
838
|
+
await fs4.writeFile(destPath, convertedContent, "utf-8");
|
|
839
|
+
copied.push(agent);
|
|
784
840
|
} catch (err) {
|
|
785
|
-
errors.push({ item, error: err.message });
|
|
841
|
+
errors.push({ item: agent, error: err.message });
|
|
786
842
|
}
|
|
787
843
|
}
|
|
788
844
|
return { copied, skipped, errors };
|
|
789
845
|
}
|
|
790
|
-
async
|
|
791
|
-
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
846
|
+
async copySkills(items, sourceDir, targetDir, mergeMode) {
|
|
847
|
+
const typeDir = join5(sourceDir, "skills");
|
|
848
|
+
const destTypeDir = join5(targetDir, "skills");
|
|
849
|
+
if (!fs4.existsSync(typeDir)) {
|
|
850
|
+
return { copied: [], skipped: [], errors: [] };
|
|
851
|
+
}
|
|
852
|
+
await fs4.ensureDir(destTypeDir);
|
|
853
|
+
let skillList;
|
|
854
|
+
if (items === "all") {
|
|
855
|
+
const entries = fs4.readdirSync(typeDir);
|
|
856
|
+
skillList = entries.filter((e) => {
|
|
857
|
+
const fullPath = join5(typeDir, e);
|
|
858
|
+
return fs4.statSync(fullPath).isDirectory() && fs4.existsSync(join5(fullPath, "SKILL.md"));
|
|
859
|
+
});
|
|
860
|
+
} else {
|
|
861
|
+
skillList = items;
|
|
862
|
+
}
|
|
863
|
+
const copied = [];
|
|
864
|
+
const skipped = [];
|
|
865
|
+
const errors = [];
|
|
866
|
+
for (const skill of skillList) {
|
|
867
|
+
try {
|
|
868
|
+
const srcPath = join5(typeDir, skill);
|
|
869
|
+
if (!fs4.existsSync(srcPath) || !fs4.statSync(srcPath).isDirectory()) {
|
|
870
|
+
skipped.push(skill);
|
|
801
871
|
continue;
|
|
802
872
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
await fs3.writeFile(destPath, tomlContent, "utf-8");
|
|
806
|
-
} else {
|
|
807
|
-
const destPath = join4(destDir, entry);
|
|
808
|
-
if (mergeMode && fs3.existsSync(destPath)) {
|
|
873
|
+
if (!fs4.existsSync(join5(srcPath, "SKILL.md"))) {
|
|
874
|
+
skipped.push(skill);
|
|
809
875
|
continue;
|
|
810
876
|
}
|
|
811
|
-
|
|
877
|
+
const destPath = join5(destTypeDir, skill);
|
|
878
|
+
if (mergeMode && fs4.existsSync(destPath)) {
|
|
879
|
+
skipped.push(skill);
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
await fs4.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
883
|
+
copied.push(skill);
|
|
884
|
+
} catch (err) {
|
|
885
|
+
errors.push({ item: skill, error: err.message });
|
|
812
886
|
}
|
|
813
887
|
}
|
|
888
|
+
return { copied, skipped, errors };
|
|
889
|
+
}
|
|
890
|
+
// Commands not supported - Codex uses skills instead
|
|
891
|
+
async copyCommands(_items, _sourceDir, _targetDir, _mergeMode) {
|
|
892
|
+
return { copied: [], skipped: [], errors: [] };
|
|
814
893
|
}
|
|
815
894
|
async copyBaseFiles(targetDir, mergeMode) {
|
|
816
895
|
const { CLI_ROOT: CLI_ROOT2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
817
|
-
const
|
|
896
|
+
const codexTemplates = join5(CLI_ROOT2, "templates", "codex");
|
|
818
897
|
const copied = [];
|
|
819
|
-
const
|
|
820
|
-
const
|
|
821
|
-
if (
|
|
822
|
-
if (!(mergeMode &&
|
|
823
|
-
await
|
|
824
|
-
copied.push("
|
|
898
|
+
const configPath = join5(codexTemplates, "config.toml");
|
|
899
|
+
const destConfigPath = join5(targetDir, "config.toml");
|
|
900
|
+
if (fs4.existsSync(configPath)) {
|
|
901
|
+
if (!(mergeMode && fs4.existsSync(destConfigPath))) {
|
|
902
|
+
await fs4.copy(configPath, destConfigPath, { overwrite: !mergeMode });
|
|
903
|
+
copied.push("config.toml");
|
|
825
904
|
}
|
|
826
905
|
}
|
|
827
906
|
return copied;
|
|
@@ -831,9 +910,9 @@ var init_gemini_adapter = __esm({
|
|
|
831
910
|
});
|
|
832
911
|
|
|
833
912
|
// src/targets/discord-adapter.ts
|
|
834
|
-
import
|
|
835
|
-
import { join as
|
|
836
|
-
function
|
|
913
|
+
import fs5 from "fs-extra";
|
|
914
|
+
import { join as join6, dirname as dirname3 } from "path";
|
|
915
|
+
function parseFrontmatter3(content) {
|
|
837
916
|
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
838
917
|
if (!match) {
|
|
839
918
|
return { frontmatter: "", body: content, description: "", argumentHint: "" };
|
|
@@ -850,10 +929,10 @@ function parseFrontmatter2(content) {
|
|
|
850
929
|
};
|
|
851
930
|
}
|
|
852
931
|
function convertAgentToDiscord(mdContent) {
|
|
853
|
-
const { frontmatter, body } =
|
|
932
|
+
const { frontmatter, body } = parseFrontmatter3(mdContent);
|
|
854
933
|
if (!frontmatter) return mdContent;
|
|
855
934
|
let converted = frontmatter;
|
|
856
|
-
for (const [claudeModel, discordModel] of Object.entries(
|
|
935
|
+
for (const [claudeModel, discordModel] of Object.entries(MODEL_MAP3)) {
|
|
857
936
|
const regex = new RegExp(`^model:\\s*${claudeModel}\\s*$`, "m");
|
|
858
937
|
if (discordModel) {
|
|
859
938
|
converted = converted.replace(regex, `model: ${discordModel}`);
|
|
@@ -891,7 +970,7 @@ function extractKeywords(content, commandName) {
|
|
|
891
970
|
return Array.from(keywords).slice(0, 10);
|
|
892
971
|
}
|
|
893
972
|
function convertCommandToSkill(mdContent, commandName) {
|
|
894
|
-
const { description, argumentHint, body } =
|
|
973
|
+
const { description, argumentHint, body } = parseFrontmatter3(mdContent);
|
|
895
974
|
const prompt = body.replace(/\$ARGUMENTS/g, "{{args}}");
|
|
896
975
|
const keywords = extractKeywords(body, commandName);
|
|
897
976
|
return `---
|
|
@@ -921,12 +1000,12 @@ ${prompt}
|
|
|
921
1000
|
Provide clear, actionable response based on the workflow above.
|
|
922
1001
|
`;
|
|
923
1002
|
}
|
|
924
|
-
var
|
|
1003
|
+
var MODEL_MAP3, DiscordAdapter;
|
|
925
1004
|
var init_discord_adapter = __esm({
|
|
926
1005
|
"src/targets/discord-adapter.ts"() {
|
|
927
1006
|
"use strict";
|
|
928
1007
|
init_base_adapter();
|
|
929
|
-
|
|
1008
|
+
MODEL_MAP3 = {
|
|
930
1009
|
"opus": "claude-3-opus",
|
|
931
1010
|
"sonnet": "claude-3-sonnet",
|
|
932
1011
|
"haiku": "claude-3-haiku",
|
|
@@ -950,15 +1029,15 @@ var init_discord_adapter = __esm({
|
|
|
950
1029
|
}
|
|
951
1030
|
};
|
|
952
1031
|
async copyAgents(items, sourceDir, targetDir, mergeMode) {
|
|
953
|
-
const typeDir =
|
|
954
|
-
const destTypeDir =
|
|
955
|
-
if (!
|
|
1032
|
+
const typeDir = join6(sourceDir, "agents");
|
|
1033
|
+
const destTypeDir = join6(targetDir, "agents");
|
|
1034
|
+
if (!fs5.existsSync(typeDir)) {
|
|
956
1035
|
return { copied: [], skipped: [], errors: [] };
|
|
957
1036
|
}
|
|
958
|
-
await
|
|
1037
|
+
await fs5.ensureDir(destTypeDir);
|
|
959
1038
|
let agentList;
|
|
960
1039
|
if (items === "all") {
|
|
961
|
-
const entries =
|
|
1040
|
+
const entries = fs5.readdirSync(typeDir);
|
|
962
1041
|
agentList = entries.filter((e) => e.endsWith(".md") && e !== "README.md").map((e) => e.replace(".md", ""));
|
|
963
1042
|
} else {
|
|
964
1043
|
agentList = items;
|
|
@@ -968,19 +1047,19 @@ var init_discord_adapter = __esm({
|
|
|
968
1047
|
const errors = [];
|
|
969
1048
|
for (const agent of agentList) {
|
|
970
1049
|
try {
|
|
971
|
-
const srcPath =
|
|
972
|
-
if (!
|
|
1050
|
+
const srcPath = join6(typeDir, agent + ".md");
|
|
1051
|
+
if (!fs5.existsSync(srcPath)) {
|
|
973
1052
|
skipped.push(agent);
|
|
974
1053
|
continue;
|
|
975
1054
|
}
|
|
976
|
-
const destPath =
|
|
977
|
-
if (mergeMode &&
|
|
1055
|
+
const destPath = join6(destTypeDir, agent + ".md");
|
|
1056
|
+
if (mergeMode && fs5.existsSync(destPath)) {
|
|
978
1057
|
skipped.push(agent);
|
|
979
1058
|
continue;
|
|
980
1059
|
}
|
|
981
|
-
const mdContent =
|
|
1060
|
+
const mdContent = fs5.readFileSync(srcPath, "utf-8");
|
|
982
1061
|
const convertedContent = convertAgentToDiscord(mdContent);
|
|
983
|
-
await
|
|
1062
|
+
await fs5.writeFile(destPath, convertedContent, "utf-8");
|
|
984
1063
|
copied.push(agent);
|
|
985
1064
|
} catch (err) {
|
|
986
1065
|
errors.push({ item: agent, error: err.message });
|
|
@@ -989,18 +1068,18 @@ var init_discord_adapter = __esm({
|
|
|
989
1068
|
return { copied, skipped, errors };
|
|
990
1069
|
}
|
|
991
1070
|
async copySkills(items, sourceDir, targetDir, mergeMode) {
|
|
992
|
-
const typeDir =
|
|
993
|
-
const destTypeDir =
|
|
994
|
-
if (!
|
|
1071
|
+
const typeDir = join6(sourceDir, "skills");
|
|
1072
|
+
const destTypeDir = join6(targetDir, "skills");
|
|
1073
|
+
if (!fs5.existsSync(typeDir)) {
|
|
995
1074
|
return { copied: [], skipped: [], errors: [] };
|
|
996
1075
|
}
|
|
997
|
-
await
|
|
1076
|
+
await fs5.ensureDir(destTypeDir);
|
|
998
1077
|
let skillList;
|
|
999
1078
|
if (items === "all") {
|
|
1000
|
-
const entries =
|
|
1079
|
+
const entries = fs5.readdirSync(typeDir);
|
|
1001
1080
|
skillList = entries.filter((e) => {
|
|
1002
|
-
const fullPath =
|
|
1003
|
-
return
|
|
1081
|
+
const fullPath = join6(typeDir, e);
|
|
1082
|
+
return fs5.statSync(fullPath).isDirectory() && fs5.existsSync(join6(fullPath, "SKILL.md"));
|
|
1004
1083
|
});
|
|
1005
1084
|
} else {
|
|
1006
1085
|
skillList = items;
|
|
@@ -1010,21 +1089,21 @@ var init_discord_adapter = __esm({
|
|
|
1010
1089
|
const errors = [];
|
|
1011
1090
|
for (const skill of skillList) {
|
|
1012
1091
|
try {
|
|
1013
|
-
const srcPath =
|
|
1014
|
-
if (!
|
|
1092
|
+
const srcPath = join6(typeDir, skill);
|
|
1093
|
+
if (!fs5.existsSync(srcPath) || !fs5.statSync(srcPath).isDirectory()) {
|
|
1015
1094
|
skipped.push(skill);
|
|
1016
1095
|
continue;
|
|
1017
1096
|
}
|
|
1018
|
-
if (!
|
|
1097
|
+
if (!fs5.existsSync(join6(srcPath, "SKILL.md"))) {
|
|
1019
1098
|
skipped.push(skill);
|
|
1020
1099
|
continue;
|
|
1021
1100
|
}
|
|
1022
|
-
const destPath =
|
|
1023
|
-
if (mergeMode &&
|
|
1101
|
+
const destPath = join6(destTypeDir, skill);
|
|
1102
|
+
if (mergeMode && fs5.existsSync(destPath)) {
|
|
1024
1103
|
skipped.push(skill);
|
|
1025
1104
|
continue;
|
|
1026
1105
|
}
|
|
1027
|
-
await
|
|
1106
|
+
await fs5.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
1028
1107
|
copied.push(skill);
|
|
1029
1108
|
} catch (err) {
|
|
1030
1109
|
errors.push({ item: skill, error: err.message });
|
|
@@ -1035,21 +1114,21 @@ var init_discord_adapter = __esm({
|
|
|
1035
1114
|
return { copied, skipped, errors };
|
|
1036
1115
|
}
|
|
1037
1116
|
async copyCommands(items, sourceDir, targetDir, mergeMode) {
|
|
1038
|
-
const typeDir =
|
|
1039
|
-
const destTypeDir =
|
|
1040
|
-
const destSkillsDir =
|
|
1041
|
-
if (!
|
|
1117
|
+
const typeDir = join6(sourceDir, "commands");
|
|
1118
|
+
const destTypeDir = join6(targetDir, "commands");
|
|
1119
|
+
const destSkillsDir = join6(targetDir, "skills");
|
|
1120
|
+
if (!fs5.existsSync(typeDir)) {
|
|
1042
1121
|
return { copied: [], skipped: [], errors: [] };
|
|
1043
1122
|
}
|
|
1044
|
-
await
|
|
1045
|
-
await
|
|
1123
|
+
await fs5.ensureDir(destTypeDir);
|
|
1124
|
+
await fs5.ensureDir(destSkillsDir);
|
|
1046
1125
|
let itemList;
|
|
1047
1126
|
if (items === "all") {
|
|
1048
|
-
const entries =
|
|
1127
|
+
const entries = fs5.readdirSync(typeDir);
|
|
1049
1128
|
itemList = entries.filter((e) => e.endsWith(".md") && e !== "README.md").map((e) => e.replace(".md", ""));
|
|
1050
1129
|
const dirs = entries.filter((e) => {
|
|
1051
|
-
const fullPath =
|
|
1052
|
-
return
|
|
1130
|
+
const fullPath = join6(typeDir, e);
|
|
1131
|
+
return fs5.statSync(fullPath).isDirectory();
|
|
1053
1132
|
});
|
|
1054
1133
|
itemList = [.../* @__PURE__ */ new Set([...itemList, ...dirs])];
|
|
1055
1134
|
} else {
|
|
@@ -1061,22 +1140,22 @@ var init_discord_adapter = __esm({
|
|
|
1061
1140
|
const commandsConfig = {};
|
|
1062
1141
|
for (const item of itemList) {
|
|
1063
1142
|
try {
|
|
1064
|
-
const srcPathMd =
|
|
1065
|
-
const srcPathDir =
|
|
1066
|
-
if (
|
|
1067
|
-
const destPath =
|
|
1068
|
-
const skillDir =
|
|
1069
|
-
const skillPath =
|
|
1070
|
-
if (!(mergeMode &&
|
|
1071
|
-
await
|
|
1072
|
-
const mdContent =
|
|
1073
|
-
await
|
|
1074
|
-
if (!(mergeMode &&
|
|
1075
|
-
await
|
|
1143
|
+
const srcPathMd = join6(typeDir, item + ".md");
|
|
1144
|
+
const srcPathDir = join6(typeDir, item);
|
|
1145
|
+
if (fs5.existsSync(srcPathMd) && fs5.statSync(srcPathMd).isFile()) {
|
|
1146
|
+
const destPath = join6(destTypeDir, item + ".md");
|
|
1147
|
+
const skillDir = join6(destSkillsDir, item.replace(/\//g, "-"));
|
|
1148
|
+
const skillPath = join6(skillDir, "SKILL.md");
|
|
1149
|
+
if (!(mergeMode && fs5.existsSync(destPath))) {
|
|
1150
|
+
await fs5.ensureDir(dirname3(destPath));
|
|
1151
|
+
const mdContent = fs5.readFileSync(srcPathMd, "utf-8");
|
|
1152
|
+
await fs5.copy(srcPathMd, destPath, { overwrite: !mergeMode });
|
|
1153
|
+
if (!(mergeMode && fs5.existsSync(skillPath))) {
|
|
1154
|
+
await fs5.ensureDir(skillDir);
|
|
1076
1155
|
const skillContent = convertCommandToSkill(mdContent, item);
|
|
1077
|
-
await
|
|
1156
|
+
await fs5.writeFile(skillPath, skillContent, "utf-8");
|
|
1078
1157
|
}
|
|
1079
|
-
const { description, body } =
|
|
1158
|
+
const { description, body } = parseFrontmatter3(mdContent);
|
|
1080
1159
|
commandsConfig[item] = {
|
|
1081
1160
|
description: description || `Execute ${item} command`,
|
|
1082
1161
|
prompt: body.replace(/\$ARGUMENTS/g, "{{args}}")
|
|
@@ -1086,7 +1165,7 @@ var init_discord_adapter = __esm({
|
|
|
1086
1165
|
skipped.push(item);
|
|
1087
1166
|
}
|
|
1088
1167
|
}
|
|
1089
|
-
if (
|
|
1168
|
+
if (fs5.existsSync(srcPathDir) && fs5.statSync(srcPathDir).isDirectory()) {
|
|
1090
1169
|
await this.copyNestedCommands(srcPathDir, destTypeDir, destSkillsDir, item, mergeMode, commandsConfig);
|
|
1091
1170
|
copied.push(item + "/*");
|
|
1092
1171
|
}
|
|
@@ -1094,20 +1173,20 @@ var init_discord_adapter = __esm({
|
|
|
1094
1173
|
errors.push({ item, error: err.message });
|
|
1095
1174
|
}
|
|
1096
1175
|
}
|
|
1097
|
-
const configPath =
|
|
1098
|
-
if (Object.keys(commandsConfig).length > 0 && !(mergeMode &&
|
|
1176
|
+
const configPath = join6(targetDir, "commands.json5");
|
|
1177
|
+
if (Object.keys(commandsConfig).length > 0 && !(mergeMode && fs5.existsSync(configPath))) {
|
|
1099
1178
|
const json5Content = this.generateCommandsJson5(commandsConfig);
|
|
1100
|
-
await
|
|
1179
|
+
await fs5.writeFile(configPath, json5Content, "utf-8");
|
|
1101
1180
|
}
|
|
1102
1181
|
return { copied, skipped, errors };
|
|
1103
1182
|
}
|
|
1104
1183
|
async copyNestedCommands(srcDir, destDir, destSkillsDir, parentName, mergeMode, commandsConfig) {
|
|
1105
|
-
const destTypeDir =
|
|
1106
|
-
await
|
|
1107
|
-
const entries =
|
|
1184
|
+
const destTypeDir = join6(destDir, parentName);
|
|
1185
|
+
await fs5.ensureDir(destTypeDir);
|
|
1186
|
+
const entries = fs5.readdirSync(srcDir);
|
|
1108
1187
|
for (const entry of entries) {
|
|
1109
|
-
const srcPath =
|
|
1110
|
-
const stat =
|
|
1188
|
+
const srcPath = join6(srcDir, entry);
|
|
1189
|
+
const stat = fs5.statSync(srcPath);
|
|
1111
1190
|
if (stat.isDirectory()) {
|
|
1112
1191
|
await this.copyNestedCommands(
|
|
1113
1192
|
srcPath,
|
|
@@ -1118,22 +1197,22 @@ var init_discord_adapter = __esm({
|
|
|
1118
1197
|
commandsConfig
|
|
1119
1198
|
);
|
|
1120
1199
|
} else if (entry.endsWith(".md") && entry !== "README.md") {
|
|
1121
|
-
const destPath =
|
|
1200
|
+
const destPath = join6(destTypeDir, entry);
|
|
1122
1201
|
const cmdName = `${parentName}/${entry.replace(".md", "")}`;
|
|
1123
1202
|
const skillName = cmdName.replace(/\//g, "-");
|
|
1124
|
-
const skillDir =
|
|
1125
|
-
const skillPath =
|
|
1126
|
-
if (mergeMode &&
|
|
1203
|
+
const skillDir = join6(destSkillsDir, skillName);
|
|
1204
|
+
const skillPath = join6(skillDir, "SKILL.md");
|
|
1205
|
+
if (mergeMode && fs5.existsSync(destPath)) {
|
|
1127
1206
|
continue;
|
|
1128
1207
|
}
|
|
1129
|
-
const mdContent =
|
|
1130
|
-
await
|
|
1131
|
-
if (!(mergeMode &&
|
|
1132
|
-
await
|
|
1208
|
+
const mdContent = fs5.readFileSync(srcPath, "utf-8");
|
|
1209
|
+
await fs5.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
1210
|
+
if (!(mergeMode && fs5.existsSync(skillPath))) {
|
|
1211
|
+
await fs5.ensureDir(skillDir);
|
|
1133
1212
|
const skillContent = convertCommandToSkill(mdContent, skillName);
|
|
1134
|
-
await
|
|
1213
|
+
await fs5.writeFile(skillPath, skillContent, "utf-8");
|
|
1135
1214
|
}
|
|
1136
|
-
const { description, body } =
|
|
1215
|
+
const { description, body } = parseFrontmatter3(mdContent);
|
|
1137
1216
|
commandsConfig[cmdName] = {
|
|
1138
1217
|
description: description || `Execute ${cmdName} command`,
|
|
1139
1218
|
prompt: body.replace(/\$ARGUMENTS/g, "{{args}}")
|
|
@@ -1163,22 +1242,22 @@ var init_discord_adapter = __esm({
|
|
|
1163
1242
|
}
|
|
1164
1243
|
async copyBundledSkills(targetDir, mergeMode) {
|
|
1165
1244
|
const { CLI_ROOT: CLI_ROOT2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
1166
|
-
const bundledSkillsDir =
|
|
1167
|
-
const destSkillsDir =
|
|
1245
|
+
const bundledSkillsDir = join6(CLI_ROOT2, "templates", "discord", "skills");
|
|
1246
|
+
const destSkillsDir = join6(targetDir, "skills");
|
|
1168
1247
|
const copied = [];
|
|
1169
|
-
if (!
|
|
1248
|
+
if (!fs5.existsSync(bundledSkillsDir)) {
|
|
1170
1249
|
return copied;
|
|
1171
1250
|
}
|
|
1172
|
-
await
|
|
1173
|
-
const skills =
|
|
1251
|
+
await fs5.ensureDir(destSkillsDir);
|
|
1252
|
+
const skills = fs5.readdirSync(bundledSkillsDir);
|
|
1174
1253
|
for (const skill of skills) {
|
|
1175
|
-
const srcPath =
|
|
1176
|
-
const destPath =
|
|
1177
|
-
if (
|
|
1178
|
-
if (mergeMode &&
|
|
1254
|
+
const srcPath = join6(bundledSkillsDir, skill);
|
|
1255
|
+
const destPath = join6(destSkillsDir, skill);
|
|
1256
|
+
if (fs5.statSync(srcPath).isDirectory()) {
|
|
1257
|
+
if (mergeMode && fs5.existsSync(destPath)) {
|
|
1179
1258
|
continue;
|
|
1180
1259
|
}
|
|
1181
|
-
await
|
|
1260
|
+
await fs5.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
1182
1261
|
copied.push(`bundled:${skill}`);
|
|
1183
1262
|
}
|
|
1184
1263
|
}
|
|
@@ -1186,17 +1265,17 @@ var init_discord_adapter = __esm({
|
|
|
1186
1265
|
}
|
|
1187
1266
|
async copyBaseFiles(targetDir, mergeMode) {
|
|
1188
1267
|
const { CLI_ROOT: CLI_ROOT2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
1189
|
-
const discordTemplates =
|
|
1268
|
+
const discordTemplates = join6(CLI_ROOT2, "templates", "discord");
|
|
1190
1269
|
const copied = [];
|
|
1191
1270
|
const filesToCopy = ["config.json5", "README.md"];
|
|
1192
1271
|
for (const file of filesToCopy) {
|
|
1193
|
-
const srcPath =
|
|
1194
|
-
const destPath =
|
|
1195
|
-
if (
|
|
1196
|
-
if (mergeMode &&
|
|
1272
|
+
const srcPath = join6(discordTemplates, file);
|
|
1273
|
+
const destPath = join6(targetDir, file);
|
|
1274
|
+
if (fs5.existsSync(srcPath)) {
|
|
1275
|
+
if (mergeMode && fs5.existsSync(destPath)) {
|
|
1197
1276
|
continue;
|
|
1198
1277
|
}
|
|
1199
|
-
await
|
|
1278
|
+
await fs5.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
1200
1279
|
copied.push(file);
|
|
1201
1280
|
}
|
|
1202
1281
|
}
|
|
@@ -1206,11 +1285,11 @@ var init_discord_adapter = __esm({
|
|
|
1206
1285
|
* Update Discord config with bot token
|
|
1207
1286
|
*/
|
|
1208
1287
|
async updateConfig(targetDir, token, guildId) {
|
|
1209
|
-
const configPath =
|
|
1210
|
-
if (!
|
|
1288
|
+
const configPath = join6(targetDir, "config.json5");
|
|
1289
|
+
if (!fs5.existsSync(configPath)) {
|
|
1211
1290
|
return;
|
|
1212
1291
|
}
|
|
1213
|
-
let content = await
|
|
1292
|
+
let content = await fs5.readFile(configPath, "utf-8");
|
|
1214
1293
|
content = content.replace(
|
|
1215
1294
|
'"token": "${DISCORD_BOT_TOKEN}"',
|
|
1216
1295
|
`"token": "${token}"`
|
|
@@ -1229,7 +1308,7 @@ var init_discord_adapter = __esm({
|
|
|
1229
1308
|
// Example guild configuration`
|
|
1230
1309
|
);
|
|
1231
1310
|
}
|
|
1232
|
-
await
|
|
1311
|
+
await fs5.writeFile(configPath, content, "utf-8");
|
|
1233
1312
|
}
|
|
1234
1313
|
/**
|
|
1235
1314
|
* Setup OpenClaw CLI configuration
|
|
@@ -1277,13 +1356,16 @@ var init_targets = __esm({
|
|
|
1277
1356
|
"use strict";
|
|
1278
1357
|
init_claude_adapter();
|
|
1279
1358
|
init_gemini_adapter();
|
|
1359
|
+
init_codex_adapter();
|
|
1280
1360
|
init_discord_adapter();
|
|
1281
1361
|
init_claude_adapter();
|
|
1282
1362
|
init_gemini_adapter();
|
|
1363
|
+
init_codex_adapter();
|
|
1283
1364
|
init_discord_adapter();
|
|
1284
1365
|
adapters = {
|
|
1285
1366
|
claude: new ClaudeAdapter(),
|
|
1286
1367
|
gemini: new GeminiAdapter(),
|
|
1368
|
+
codex: new CodexAdapter(),
|
|
1287
1369
|
discord: new DiscordAdapter()
|
|
1288
1370
|
};
|
|
1289
1371
|
}
|
|
@@ -1291,23 +1373,23 @@ var init_targets = __esm({
|
|
|
1291
1373
|
|
|
1292
1374
|
// src/utils/hash.ts
|
|
1293
1375
|
import { createHash } from "crypto";
|
|
1294
|
-
import
|
|
1295
|
-
import { join as
|
|
1376
|
+
import fs6 from "fs-extra";
|
|
1377
|
+
import { join as join7, relative } from "path";
|
|
1296
1378
|
function hashFile(filePath) {
|
|
1297
|
-
if (!
|
|
1379
|
+
if (!fs6.existsSync(filePath)) {
|
|
1298
1380
|
return null;
|
|
1299
1381
|
}
|
|
1300
|
-
const content =
|
|
1382
|
+
const content = fs6.readFileSync(filePath);
|
|
1301
1383
|
return createHash("md5").update(content).digest("hex");
|
|
1302
1384
|
}
|
|
1303
1385
|
async function hashDirectory(dirPath, baseDir = dirPath) {
|
|
1304
1386
|
const hashes = {};
|
|
1305
|
-
if (!
|
|
1387
|
+
if (!fs6.existsSync(dirPath)) {
|
|
1306
1388
|
return hashes;
|
|
1307
1389
|
}
|
|
1308
|
-
const items = await
|
|
1390
|
+
const items = await fs6.readdir(dirPath, { withFileTypes: true });
|
|
1309
1391
|
for (const item of items) {
|
|
1310
|
-
const itemPath =
|
|
1392
|
+
const itemPath = join7(dirPath, item.name);
|
|
1311
1393
|
const relativePath = relative(baseDir, itemPath);
|
|
1312
1394
|
if (item.isDirectory()) {
|
|
1313
1395
|
const subHashes = await hashDirectory(itemPath, baseDir);
|
|
@@ -1328,27 +1410,27 @@ var init_hash = __esm({
|
|
|
1328
1410
|
});
|
|
1329
1411
|
|
|
1330
1412
|
// src/utils/state.ts
|
|
1331
|
-
import
|
|
1332
|
-
import { join as
|
|
1413
|
+
import fs7 from "fs-extra";
|
|
1414
|
+
import { join as join8 } from "path";
|
|
1333
1415
|
function getStatePath(projectDir) {
|
|
1334
|
-
return
|
|
1416
|
+
return join8(projectDir, STATE_DIR, STATE_FILE);
|
|
1335
1417
|
}
|
|
1336
1418
|
async function loadState(projectDir) {
|
|
1337
1419
|
const statePath = getStatePath(projectDir);
|
|
1338
|
-
if (!
|
|
1420
|
+
if (!fs7.existsSync(statePath)) {
|
|
1339
1421
|
return null;
|
|
1340
1422
|
}
|
|
1341
1423
|
try {
|
|
1342
|
-
return await
|
|
1424
|
+
return await fs7.readJson(statePath);
|
|
1343
1425
|
} catch {
|
|
1344
1426
|
return null;
|
|
1345
1427
|
}
|
|
1346
1428
|
}
|
|
1347
1429
|
async function saveState(projectDir, state) {
|
|
1348
|
-
const stateDir =
|
|
1349
|
-
const statePath =
|
|
1350
|
-
await
|
|
1351
|
-
await
|
|
1430
|
+
const stateDir = join8(projectDir, STATE_DIR);
|
|
1431
|
+
const statePath = join8(stateDir, STATE_FILE);
|
|
1432
|
+
await fs7.ensureDir(stateDir);
|
|
1433
|
+
await fs7.writeJson(statePath, state, { spaces: 2 });
|
|
1352
1434
|
}
|
|
1353
1435
|
async function createInitialState(projectDir, options) {
|
|
1354
1436
|
const { kit, source, target, targets, installed } = options;
|
|
@@ -1356,8 +1438,8 @@ async function createInitialState(projectDir, options) {
|
|
|
1356
1438
|
const targetList = targets || [target.replace(".", "")];
|
|
1357
1439
|
for (const t of targetList) {
|
|
1358
1440
|
const targetDirName = t.startsWith(".") ? t : `.${t}`;
|
|
1359
|
-
const targetDir =
|
|
1360
|
-
if (
|
|
1441
|
+
const targetDir = join8(projectDir, targetDirName);
|
|
1442
|
+
if (fs7.existsSync(targetDir)) {
|
|
1361
1443
|
const hashes = await hashDirectory(targetDir);
|
|
1362
1444
|
for (const [path, hash] of Object.entries(hashes)) {
|
|
1363
1445
|
allHashes[`${targetDirName}/${path}`] = hash;
|
|
@@ -1383,7 +1465,7 @@ async function updateState(projectDir, updates) {
|
|
|
1383
1465
|
if (!state) {
|
|
1384
1466
|
throw new Error("No state found. Is this an ak project?");
|
|
1385
1467
|
}
|
|
1386
|
-
const targetDir =
|
|
1468
|
+
const targetDir = join8(projectDir, state.target || ".claude");
|
|
1387
1469
|
const newHashes = await hashDirectory(targetDir);
|
|
1388
1470
|
const updatedState = {
|
|
1389
1471
|
...state,
|
|
@@ -1399,7 +1481,7 @@ async function getFileStatuses(projectDir) {
|
|
|
1399
1481
|
if (!state) {
|
|
1400
1482
|
return { error: "No state found" };
|
|
1401
1483
|
}
|
|
1402
|
-
const targetDir =
|
|
1484
|
+
const targetDir = join8(projectDir, state.target || ".claude");
|
|
1403
1485
|
const currentHashes = await hashDirectory(targetDir);
|
|
1404
1486
|
const originalHashes = state.originalHashes || {};
|
|
1405
1487
|
const statuses = {
|
|
@@ -1439,38 +1521,38 @@ var init_state = __esm({
|
|
|
1439
1521
|
});
|
|
1440
1522
|
|
|
1441
1523
|
// src/utils/copy.ts
|
|
1442
|
-
import
|
|
1443
|
-
import { join as
|
|
1524
|
+
import fs8 from "fs-extra";
|
|
1525
|
+
import { join as join9, dirname as dirname4 } from "path";
|
|
1444
1526
|
async function copyItems(items, type, sourceDir, destDir, mergeMode = false) {
|
|
1445
|
-
const typeDir =
|
|
1446
|
-
const destTypeDir =
|
|
1447
|
-
if (!
|
|
1527
|
+
const typeDir = join9(sourceDir, type);
|
|
1528
|
+
const destTypeDir = join9(destDir, type);
|
|
1529
|
+
if (!fs8.existsSync(typeDir)) {
|
|
1448
1530
|
return { copied: [], skipped: items, errors: [] };
|
|
1449
1531
|
}
|
|
1450
|
-
await
|
|
1532
|
+
await fs8.ensureDir(destTypeDir);
|
|
1451
1533
|
const copied = [];
|
|
1452
1534
|
const skipped = [];
|
|
1453
1535
|
const errors = [];
|
|
1454
1536
|
for (const item of items) {
|
|
1455
1537
|
try {
|
|
1456
|
-
const itemPath =
|
|
1538
|
+
const itemPath = join9(typeDir, item);
|
|
1457
1539
|
const itemPathMd = itemPath + ".md";
|
|
1458
1540
|
let srcPath;
|
|
1459
|
-
if (
|
|
1541
|
+
if (fs8.existsSync(itemPath)) {
|
|
1460
1542
|
srcPath = itemPath;
|
|
1461
|
-
} else if (
|
|
1543
|
+
} else if (fs8.existsSync(itemPathMd)) {
|
|
1462
1544
|
srcPath = itemPathMd;
|
|
1463
1545
|
} else {
|
|
1464
1546
|
skipped.push(item);
|
|
1465
1547
|
continue;
|
|
1466
1548
|
}
|
|
1467
|
-
const stat =
|
|
1549
|
+
const stat = fs8.statSync(srcPath);
|
|
1468
1550
|
if (stat.isDirectory()) {
|
|
1469
|
-
await
|
|
1551
|
+
await fs8.copy(srcPath, join9(destTypeDir, item), { overwrite: !mergeMode });
|
|
1470
1552
|
} else {
|
|
1471
|
-
const destPath = srcPath.endsWith(".md") ?
|
|
1472
|
-
await
|
|
1473
|
-
await
|
|
1553
|
+
const destPath = srcPath.endsWith(".md") ? join9(destTypeDir, item + ".md") : join9(destTypeDir, item);
|
|
1554
|
+
await fs8.ensureDir(join9(destTypeDir, item.split("/").slice(0, -1).join("/")));
|
|
1555
|
+
await fs8.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
1474
1556
|
}
|
|
1475
1557
|
copied.push(item);
|
|
1476
1558
|
} catch (err) {
|
|
@@ -1480,25 +1562,25 @@ async function copyItems(items, type, sourceDir, destDir, mergeMode = false) {
|
|
|
1480
1562
|
return { copied, skipped, errors };
|
|
1481
1563
|
}
|
|
1482
1564
|
async function copyAgentsMd(agentsMdPath, projectDir, mergeMode = false) {
|
|
1483
|
-
if (!agentsMdPath || !
|
|
1565
|
+
if (!agentsMdPath || !fs8.existsSync(agentsMdPath)) {
|
|
1484
1566
|
return false;
|
|
1485
1567
|
}
|
|
1486
|
-
const destPath =
|
|
1487
|
-
if (mergeMode &&
|
|
1568
|
+
const destPath = join9(projectDir, "AGENTS.md");
|
|
1569
|
+
if (mergeMode && fs8.existsSync(destPath)) {
|
|
1488
1570
|
return false;
|
|
1489
1571
|
}
|
|
1490
|
-
await
|
|
1572
|
+
await fs8.copy(agentsMdPath, destPath, { overwrite: !mergeMode });
|
|
1491
1573
|
return true;
|
|
1492
1574
|
}
|
|
1493
1575
|
function listAvailable(type, sourceDir) {
|
|
1494
|
-
const typeDir =
|
|
1495
|
-
if (!
|
|
1576
|
+
const typeDir = join9(sourceDir, type);
|
|
1577
|
+
if (!fs8.existsSync(typeDir)) {
|
|
1496
1578
|
return [];
|
|
1497
1579
|
}
|
|
1498
|
-
const items =
|
|
1580
|
+
const items = fs8.readdirSync(typeDir);
|
|
1499
1581
|
return items.map((item) => {
|
|
1500
|
-
const itemPath =
|
|
1501
|
-
const isDir =
|
|
1582
|
+
const itemPath = join9(typeDir, item);
|
|
1583
|
+
const isDir = fs8.statSync(itemPath).isDirectory();
|
|
1502
1584
|
const name = item.replace(/\.md$/, "");
|
|
1503
1585
|
return { name, isDir, path: itemPath };
|
|
1504
1586
|
});
|
|
@@ -1648,10 +1730,10 @@ function isGeminiCliInstalled() {
|
|
|
1648
1730
|
}
|
|
1649
1731
|
function isGeminiCliLoggedIn() {
|
|
1650
1732
|
try {
|
|
1651
|
-
const
|
|
1733
|
+
const fs16 = __require("fs");
|
|
1652
1734
|
const path = __require("path");
|
|
1653
1735
|
const credsPath = path.join(process.env.HOME || "", ".gemini", "oauth_creds.json");
|
|
1654
|
-
return
|
|
1736
|
+
return fs16.existsSync(credsPath);
|
|
1655
1737
|
} catch {
|
|
1656
1738
|
return false;
|
|
1657
1739
|
}
|
|
@@ -1890,8 +1972,8 @@ var init_exports = {};
|
|
|
1890
1972
|
__export(init_exports, {
|
|
1891
1973
|
initCommand: () => initCommand
|
|
1892
1974
|
});
|
|
1893
|
-
import
|
|
1894
|
-
import { join as
|
|
1975
|
+
import fs9 from "fs-extra";
|
|
1976
|
+
import { join as join10, resolve as resolve2 } from "path";
|
|
1895
1977
|
import pc2 from "picocolors";
|
|
1896
1978
|
import ora from "ora";
|
|
1897
1979
|
function filterComponents(list, exclude, only) {
|
|
@@ -1965,18 +2047,18 @@ async function initCommand(projectName, options) {
|
|
|
1965
2047
|
let existingAction = null;
|
|
1966
2048
|
const existingTargets = [];
|
|
1967
2049
|
for (const target of cliTargets) {
|
|
1968
|
-
const targetDir =
|
|
1969
|
-
if (options.fresh &&
|
|
1970
|
-
await
|
|
2050
|
+
const targetDir = join10(projectDir, getTargetDirectory(target));
|
|
2051
|
+
if (options.fresh && fs9.existsSync(targetDir)) {
|
|
2052
|
+
await fs9.remove(targetDir);
|
|
1971
2053
|
existingTargets.push(getTargetDisplayName(target));
|
|
1972
|
-
} else if (
|
|
2054
|
+
} else if (fs9.existsSync(targetDir) && !options.force) {
|
|
1973
2055
|
existingTargets.push(getTargetDisplayName(target));
|
|
1974
2056
|
}
|
|
1975
2057
|
}
|
|
1976
2058
|
if (options.fresh && existingTargets.length > 0) {
|
|
1977
|
-
const akDir =
|
|
1978
|
-
if (
|
|
1979
|
-
await
|
|
2059
|
+
const akDir = join10(projectDir, ".ak");
|
|
2060
|
+
if (fs9.existsSync(akDir)) {
|
|
2061
|
+
await fs9.remove(akDir);
|
|
1980
2062
|
}
|
|
1981
2063
|
console.log(pc2.cyan(`Fresh install: removed existing files (${existingTargets.join(", ")})`));
|
|
1982
2064
|
existingAction = null;
|
|
@@ -1996,8 +2078,8 @@ async function initCommand(projectName, options) {
|
|
|
1996
2078
|
}
|
|
1997
2079
|
}
|
|
1998
2080
|
}
|
|
1999
|
-
if (!isCurrentDir &&
|
|
2000
|
-
const files =
|
|
2081
|
+
if (!isCurrentDir && fs9.existsSync(projectDir) && !options.force) {
|
|
2082
|
+
const files = fs9.readdirSync(projectDir);
|
|
2001
2083
|
if (files.length > 0 && !existingAction) {
|
|
2002
2084
|
console.log(pc2.red(`Directory "${projectName}" already exists and is not empty.`));
|
|
2003
2085
|
console.log(pc2.gray("Use --force to overwrite."));
|
|
@@ -2078,22 +2160,22 @@ async function initCommand(projectName, options) {
|
|
|
2078
2160
|
}
|
|
2079
2161
|
const spinner = ora("Creating project...").start();
|
|
2080
2162
|
try {
|
|
2081
|
-
await
|
|
2163
|
+
await fs9.ensureDir(projectDir);
|
|
2082
2164
|
for (const target of cliTargets) {
|
|
2083
2165
|
const adapter = getAdapter(target);
|
|
2084
|
-
const targetDir =
|
|
2085
|
-
await
|
|
2166
|
+
const targetDir = join10(projectDir, adapter.config.directory);
|
|
2167
|
+
await fs9.ensureDir(targetDir);
|
|
2086
2168
|
const targetLabel = adapter.config.displayName;
|
|
2087
2169
|
if (kitName === "full" && target === "claude") {
|
|
2088
2170
|
spinner.text = mergeMode ? `Merging full kit (${targetLabel})...` : `Copying full kit (${targetLabel})...`;
|
|
2089
|
-
const items = await
|
|
2171
|
+
const items = await fs9.readdir(source.claudeDir);
|
|
2090
2172
|
for (const item of items) {
|
|
2091
|
-
const srcPath =
|
|
2092
|
-
const destPath =
|
|
2093
|
-
if (mergeMode && await
|
|
2173
|
+
const srcPath = join10(source.claudeDir, item);
|
|
2174
|
+
const destPath = join10(targetDir, item);
|
|
2175
|
+
if (mergeMode && await fs9.pathExists(destPath)) {
|
|
2094
2176
|
continue;
|
|
2095
2177
|
}
|
|
2096
|
-
await
|
|
2178
|
+
await fs9.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
2097
2179
|
}
|
|
2098
2180
|
continue;
|
|
2099
2181
|
}
|
|
@@ -2218,8 +2300,8 @@ var add_exports = {};
|
|
|
2218
2300
|
__export(add_exports, {
|
|
2219
2301
|
addCommand: () => addCommand
|
|
2220
2302
|
});
|
|
2221
|
-
import
|
|
2222
|
-
import { join as
|
|
2303
|
+
import fs10 from "fs-extra";
|
|
2304
|
+
import { join as join11 } from "path";
|
|
2223
2305
|
import pc3 from "picocolors";
|
|
2224
2306
|
import ora2 from "ora";
|
|
2225
2307
|
async function addCommand(item, options = {}) {
|
|
@@ -2274,10 +2356,10 @@ async function addCommand(item, options = {}) {
|
|
|
2274
2356
|
return;
|
|
2275
2357
|
}
|
|
2276
2358
|
const targetFolder = state?.target || ".claude";
|
|
2277
|
-
const targetDir =
|
|
2278
|
-
const destPath =
|
|
2359
|
+
const targetDir = join11(projectDir, targetFolder);
|
|
2360
|
+
const destPath = join11(targetDir, normalizedType, name);
|
|
2279
2361
|
const destPathMd = destPath + ".md";
|
|
2280
|
-
if (
|
|
2362
|
+
if (fs10.existsSync(destPath) || fs10.existsSync(destPathMd)) {
|
|
2281
2363
|
console.log(pc3.yellow(`${type} "${name}" already exists in project.`));
|
|
2282
2364
|
console.log(pc3.gray('Use "tk update" to refresh from source.'));
|
|
2283
2365
|
return;
|
|
@@ -2493,8 +2575,8 @@ var update_exports = {};
|
|
|
2493
2575
|
__export(update_exports, {
|
|
2494
2576
|
updateCommand: () => updateCommand
|
|
2495
2577
|
});
|
|
2496
|
-
import
|
|
2497
|
-
import { join as
|
|
2578
|
+
import fs11 from "fs-extra";
|
|
2579
|
+
import { join as join12 } from "path";
|
|
2498
2580
|
import pc5 from "picocolors";
|
|
2499
2581
|
import ora3 from "ora";
|
|
2500
2582
|
async function updateCommand(options = {}) {
|
|
@@ -2533,8 +2615,8 @@ async function updateCommand(options = {}) {
|
|
|
2533
2615
|
if (options.commands) typesToUpdate = ["commands"];
|
|
2534
2616
|
const sourceHashes = {};
|
|
2535
2617
|
for (const type of typesToUpdate) {
|
|
2536
|
-
const typeDir =
|
|
2537
|
-
if (
|
|
2618
|
+
const typeDir = join12(source.claudeDir, type);
|
|
2619
|
+
if (fs11.existsSync(typeDir)) {
|
|
2538
2620
|
const hashes = await hashDirectory(typeDir);
|
|
2539
2621
|
for (const [path, hash] of Object.entries(hashes)) {
|
|
2540
2622
|
sourceHashes[`${type}/${path}`] = hash;
|
|
@@ -2545,9 +2627,9 @@ async function updateCommand(options = {}) {
|
|
|
2545
2627
|
const skipped = [];
|
|
2546
2628
|
const newFiles = [];
|
|
2547
2629
|
for (const [path, sourceHash] of Object.entries(sourceHashes)) {
|
|
2548
|
-
const currentPath =
|
|
2630
|
+
const currentPath = join12(targetDir, path);
|
|
2549
2631
|
const originalHash = state.originalHashes?.[path];
|
|
2550
|
-
const currentHash =
|
|
2632
|
+
const currentHash = fs11.existsSync(currentPath) ? hashFile(currentPath) : null;
|
|
2551
2633
|
if (!currentHash) {
|
|
2552
2634
|
newFiles.push(path);
|
|
2553
2635
|
} else if (currentHash === originalHash) {
|
|
@@ -2600,10 +2682,10 @@ async function updateCommand(options = {}) {
|
|
|
2600
2682
|
let failed = 0;
|
|
2601
2683
|
for (const path of [...toUpdate, ...newFiles]) {
|
|
2602
2684
|
try {
|
|
2603
|
-
const srcPath =
|
|
2604
|
-
const destPath =
|
|
2605
|
-
await
|
|
2606
|
-
await
|
|
2685
|
+
const srcPath = join12(source.claudeDir, path);
|
|
2686
|
+
const destPath = join12(targetDir, path);
|
|
2687
|
+
await fs11.ensureDir(join12(targetDir, path.split("/").slice(0, -1).join("/")));
|
|
2688
|
+
await fs11.copy(srcPath, destPath, { overwrite: true });
|
|
2607
2689
|
updated++;
|
|
2608
2690
|
} catch (err) {
|
|
2609
2691
|
failed++;
|
|
@@ -2653,7 +2735,7 @@ __export(status_exports, {
|
|
|
2653
2735
|
statusCommand: () => statusCommand
|
|
2654
2736
|
});
|
|
2655
2737
|
import pc6 from "picocolors";
|
|
2656
|
-
import
|
|
2738
|
+
import fs12 from "fs-extra";
|
|
2657
2739
|
async function statusCommand(options = {}) {
|
|
2658
2740
|
const projectDir = process.cwd();
|
|
2659
2741
|
if (!isAkProject(projectDir)) {
|
|
@@ -2734,7 +2816,7 @@ async function statusCommand(options = {}) {
|
|
|
2734
2816
|
if (hooks) console.log(pc6.gray(" Hooks: \u2713"));
|
|
2735
2817
|
console.log("");
|
|
2736
2818
|
}
|
|
2737
|
-
if (state.source && !
|
|
2819
|
+
if (state.source && !fs12.existsSync(state.source)) {
|
|
2738
2820
|
console.log(pc6.yellow("\u26A0 Source directory not found. Update may not work."));
|
|
2739
2821
|
console.log(pc6.gray(` Expected: ${state.source}`));
|
|
2740
2822
|
console.log("");
|
|
@@ -2753,15 +2835,15 @@ var doctor_exports = {};
|
|
|
2753
2835
|
__export(doctor_exports, {
|
|
2754
2836
|
doctorCommand: () => doctorCommand
|
|
2755
2837
|
});
|
|
2756
|
-
import
|
|
2757
|
-
import { join as
|
|
2838
|
+
import fs13 from "fs-extra";
|
|
2839
|
+
import { join as join13 } from "path";
|
|
2758
2840
|
import pc7 from "picocolors";
|
|
2759
2841
|
async function doctorCommand(options = {}) {
|
|
2760
2842
|
const projectDir = process.cwd();
|
|
2761
2843
|
let targetDir = null;
|
|
2762
2844
|
for (const [name, folder] of Object.entries(TARGETS)) {
|
|
2763
|
-
const dir =
|
|
2764
|
-
if (
|
|
2845
|
+
const dir = join13(projectDir, folder);
|
|
2846
|
+
if (fs13.existsSync(dir)) {
|
|
2765
2847
|
targetDir = { name, folder, dir };
|
|
2766
2848
|
break;
|
|
2767
2849
|
}
|
|
@@ -2774,7 +2856,7 @@ async function doctorCommand(options = {}) {
|
|
|
2774
2856
|
severity: "error",
|
|
2775
2857
|
check: () => isAkProject(projectDir),
|
|
2776
2858
|
fix: async () => {
|
|
2777
|
-
await
|
|
2859
|
+
await fs13.ensureDir(join13(projectDir, ".ak"));
|
|
2778
2860
|
}
|
|
2779
2861
|
},
|
|
2780
2862
|
{
|
|
@@ -2790,9 +2872,9 @@ async function doctorCommand(options = {}) {
|
|
|
2790
2872
|
if (targetDir) {
|
|
2791
2873
|
const dirs = ["agents", "skills", "commands", "workflows"];
|
|
2792
2874
|
for (const dir of dirs) {
|
|
2793
|
-
const fullPath =
|
|
2794
|
-
if (
|
|
2795
|
-
const items =
|
|
2875
|
+
const fullPath = join13(targetDir.dir, dir);
|
|
2876
|
+
if (fs13.existsSync(fullPath)) {
|
|
2877
|
+
const items = fs13.readdirSync(fullPath).filter((f) => !f.startsWith("."));
|
|
2796
2878
|
if (items.length > 0) {
|
|
2797
2879
|
installed[dir] = items;
|
|
2798
2880
|
}
|
|
@@ -2814,7 +2896,7 @@ async function doctorCommand(options = {}) {
|
|
|
2814
2896
|
name: "agents_md",
|
|
2815
2897
|
label: "AGENTS.md exists",
|
|
2816
2898
|
severity: "warning",
|
|
2817
|
-
check: () =>
|
|
2899
|
+
check: () => fs13.existsSync(join13(projectDir, "AGENTS.md"))
|
|
2818
2900
|
},
|
|
2819
2901
|
{
|
|
2820
2902
|
name: "source",
|
|
@@ -2822,7 +2904,7 @@ async function doctorCommand(options = {}) {
|
|
|
2822
2904
|
severity: "error",
|
|
2823
2905
|
check: () => {
|
|
2824
2906
|
if (!state || !state.source) return true;
|
|
2825
|
-
return
|
|
2907
|
+
return fs13.existsSync(state.source);
|
|
2826
2908
|
},
|
|
2827
2909
|
getMeta: () => state && state.source ? { source: state.source } : {}
|
|
2828
2910
|
},
|
|
@@ -2832,18 +2914,18 @@ async function doctorCommand(options = {}) {
|
|
|
2832
2914
|
severity: "warning",
|
|
2833
2915
|
check: () => {
|
|
2834
2916
|
if (!targetDir) return false;
|
|
2835
|
-
return
|
|
2917
|
+
return fs13.existsSync(join13(targetDir.dir, "agents"));
|
|
2836
2918
|
},
|
|
2837
2919
|
fix: async () => {
|
|
2838
2920
|
if (targetDir) {
|
|
2839
|
-
await
|
|
2921
|
+
await fs13.ensureDir(join13(targetDir.dir, "agents"));
|
|
2840
2922
|
}
|
|
2841
2923
|
},
|
|
2842
2924
|
getMeta: () => {
|
|
2843
2925
|
if (!targetDir) return {};
|
|
2844
|
-
const fullPath =
|
|
2845
|
-
if (
|
|
2846
|
-
const items =
|
|
2926
|
+
const fullPath = join13(targetDir.dir, "agents");
|
|
2927
|
+
if (fs13.existsSync(fullPath)) {
|
|
2928
|
+
const items = fs13.readdirSync(fullPath).length;
|
|
2847
2929
|
return { items };
|
|
2848
2930
|
}
|
|
2849
2931
|
return {};
|
|
@@ -2855,18 +2937,18 @@ async function doctorCommand(options = {}) {
|
|
|
2855
2937
|
severity: "warning",
|
|
2856
2938
|
check: () => {
|
|
2857
2939
|
if (!targetDir) return false;
|
|
2858
|
-
return
|
|
2940
|
+
return fs13.existsSync(join13(targetDir.dir, "commands"));
|
|
2859
2941
|
},
|
|
2860
2942
|
fix: async () => {
|
|
2861
2943
|
if (targetDir) {
|
|
2862
|
-
await
|
|
2944
|
+
await fs13.ensureDir(join13(targetDir.dir, "commands"));
|
|
2863
2945
|
}
|
|
2864
2946
|
},
|
|
2865
2947
|
getMeta: () => {
|
|
2866
2948
|
if (!targetDir) return {};
|
|
2867
|
-
const fullPath =
|
|
2868
|
-
if (
|
|
2869
|
-
const items =
|
|
2949
|
+
const fullPath = join13(targetDir.dir, "commands");
|
|
2950
|
+
if (fs13.existsSync(fullPath)) {
|
|
2951
|
+
const items = fs13.readdirSync(fullPath).length;
|
|
2870
2952
|
return { items };
|
|
2871
2953
|
}
|
|
2872
2954
|
return {};
|
|
@@ -2878,18 +2960,18 @@ async function doctorCommand(options = {}) {
|
|
|
2878
2960
|
severity: "warning",
|
|
2879
2961
|
check: () => {
|
|
2880
2962
|
if (!targetDir) return false;
|
|
2881
|
-
return
|
|
2963
|
+
return fs13.existsSync(join13(targetDir.dir, "skills"));
|
|
2882
2964
|
},
|
|
2883
2965
|
fix: async () => {
|
|
2884
2966
|
if (targetDir) {
|
|
2885
|
-
await
|
|
2967
|
+
await fs13.ensureDir(join13(targetDir.dir, "skills"));
|
|
2886
2968
|
}
|
|
2887
2969
|
},
|
|
2888
2970
|
getMeta: () => {
|
|
2889
2971
|
if (!targetDir) return {};
|
|
2890
|
-
const fullPath =
|
|
2891
|
-
if (
|
|
2892
|
-
const items =
|
|
2972
|
+
const fullPath = join13(targetDir.dir, "skills");
|
|
2973
|
+
if (fs13.existsSync(fullPath)) {
|
|
2974
|
+
const items = fs13.readdirSync(fullPath).length;
|
|
2893
2975
|
return { items };
|
|
2894
2976
|
}
|
|
2895
2977
|
return {};
|
|
@@ -2901,7 +2983,7 @@ async function doctorCommand(options = {}) {
|
|
|
2901
2983
|
severity: "warning",
|
|
2902
2984
|
check: () => {
|
|
2903
2985
|
if (!targetDir) return false;
|
|
2904
|
-
return
|
|
2986
|
+
return fs13.existsSync(join13(targetDir.dir, "scripts"));
|
|
2905
2987
|
}
|
|
2906
2988
|
},
|
|
2907
2989
|
{
|
|
@@ -2910,7 +2992,7 @@ async function doctorCommand(options = {}) {
|
|
|
2910
2992
|
severity: "warning",
|
|
2911
2993
|
check: () => {
|
|
2912
2994
|
if (!targetDir) return false;
|
|
2913
|
-
return
|
|
2995
|
+
return fs13.existsSync(join13(targetDir.dir, "hooks"));
|
|
2914
2996
|
}
|
|
2915
2997
|
},
|
|
2916
2998
|
{
|
|
@@ -2919,7 +3001,7 @@ async function doctorCommand(options = {}) {
|
|
|
2919
3001
|
severity: "warning",
|
|
2920
3002
|
check: () => {
|
|
2921
3003
|
if (!targetDir) return false;
|
|
2922
|
-
return
|
|
3004
|
+
return fs13.existsSync(join13(targetDir.dir, "statusline.cjs")) || fs13.existsSync(join13(targetDir.dir, "statusline.sh"));
|
|
2923
3005
|
}
|
|
2924
3006
|
}
|
|
2925
3007
|
];
|
|
@@ -3077,9 +3159,9 @@ async function outputReport(projectDir, results, options) {
|
|
|
3077
3159
|
}
|
|
3078
3160
|
}
|
|
3079
3161
|
}
|
|
3080
|
-
const reportPath =
|
|
3081
|
-
await
|
|
3082
|
-
await
|
|
3162
|
+
const reportPath = join13(projectDir, ".ak", "doctor-report.md");
|
|
3163
|
+
await fs13.ensureDir(join13(projectDir, ".ak"));
|
|
3164
|
+
await fs13.writeFile(reportPath, markdown, "utf-8");
|
|
3083
3165
|
if (!options.json) {
|
|
3084
3166
|
console.log(pc7.green(`
|
|
3085
3167
|
\u2713 Report saved to ${reportPath}
|
|
@@ -3152,7 +3234,7 @@ async function outputColored(projectDir, results, state, targetDir) {
|
|
|
3152
3234
|
if (!hasState && isProject) {
|
|
3153
3235
|
console.log(pc7.white(' \u2022 State file is missing. Re-run "tk init" or create manually'));
|
|
3154
3236
|
}
|
|
3155
|
-
if (state && state.source && !
|
|
3237
|
+
if (state && state.source && !fs13.existsSync(state.source)) {
|
|
3156
3238
|
console.log(pc7.white(" \u2022 Update source path: tk update --source <new-path>"));
|
|
3157
3239
|
}
|
|
3158
3240
|
console.log("");
|
|
@@ -3193,8 +3275,8 @@ var uninstall_exports = {};
|
|
|
3193
3275
|
__export(uninstall_exports, {
|
|
3194
3276
|
uninstallCommand: () => uninstallCommand
|
|
3195
3277
|
});
|
|
3196
|
-
import
|
|
3197
|
-
import { join as
|
|
3278
|
+
import fs14 from "fs-extra";
|
|
3279
|
+
import { join as join14 } from "path";
|
|
3198
3280
|
import pc9 from "picocolors";
|
|
3199
3281
|
import ora4 from "ora";
|
|
3200
3282
|
import * as p2 from "@clack/prompts";
|
|
@@ -3223,13 +3305,13 @@ async function uninstallFromDir(type, dir, options) {
|
|
|
3223
3305
|
const state = await loadState(dir);
|
|
3224
3306
|
const existingTargets = [];
|
|
3225
3307
|
for (const [name, folder] of Object.entries(TARGETS)) {
|
|
3226
|
-
const targetPath =
|
|
3227
|
-
if (
|
|
3308
|
+
const targetPath = join14(dir, folder);
|
|
3309
|
+
if (fs14.existsSync(targetPath)) {
|
|
3228
3310
|
existingTargets.push({ name, path: targetPath });
|
|
3229
3311
|
}
|
|
3230
3312
|
}
|
|
3231
|
-
const akDir =
|
|
3232
|
-
const hasAkState =
|
|
3313
|
+
const akDir = join14(dir, ".ak");
|
|
3314
|
+
const hasAkState = fs14.existsSync(akDir);
|
|
3233
3315
|
if (existingTargets.length === 0 && !hasAkState) {
|
|
3234
3316
|
spinner.warn(pc9.yellow(`No AK installation found in ${type}`));
|
|
3235
3317
|
return 0;
|
|
@@ -3238,8 +3320,8 @@ async function uninstallFromDir(type, dir, options) {
|
|
|
3238
3320
|
const removalList = [];
|
|
3239
3321
|
for (const target of existingTargets) {
|
|
3240
3322
|
for (const subdir of AK_SUBDIRS) {
|
|
3241
|
-
const subdirPath =
|
|
3242
|
-
if (
|
|
3323
|
+
const subdirPath = join14(target.path, subdir);
|
|
3324
|
+
if (fs14.existsSync(subdirPath)) {
|
|
3243
3325
|
removalList.push(subdirPath);
|
|
3244
3326
|
}
|
|
3245
3327
|
}
|
|
@@ -3320,7 +3402,7 @@ async function removeItems(paths, baseDir) {
|
|
|
3320
3402
|
continue;
|
|
3321
3403
|
}
|
|
3322
3404
|
try {
|
|
3323
|
-
await
|
|
3405
|
+
await fs14.remove(path);
|
|
3324
3406
|
result.removed.push(path);
|
|
3325
3407
|
} catch (error) {
|
|
3326
3408
|
result.errors.push({
|
|
@@ -3434,10 +3516,10 @@ import { execSync as execSync2 } from "child_process";
|
|
|
3434
3516
|
import pc11 from "picocolors";
|
|
3435
3517
|
import ora6 from "ora";
|
|
3436
3518
|
import { readFileSync } from "fs";
|
|
3437
|
-
import { join as
|
|
3519
|
+
import { join as join15 } from "path";
|
|
3438
3520
|
function getCurrentVersion() {
|
|
3439
3521
|
try {
|
|
3440
|
-
const pkg = JSON.parse(readFileSync(
|
|
3522
|
+
const pkg = JSON.parse(readFileSync(join15(CLI_ROOT, "package.json"), "utf-8"));
|
|
3441
3523
|
return pkg.version;
|
|
3442
3524
|
} catch {
|
|
3443
3525
|
return "0.0.0";
|
|
@@ -3497,8 +3579,8 @@ __export(skills_exports, {
|
|
|
3497
3579
|
skillsCommand: () => skillsCommand
|
|
3498
3580
|
});
|
|
3499
3581
|
import pc12 from "picocolors";
|
|
3500
|
-
import
|
|
3501
|
-
import { join as
|
|
3582
|
+
import fs15 from "fs-extra";
|
|
3583
|
+
import { join as join16 } from "path";
|
|
3502
3584
|
import * as p3 from "@clack/prompts";
|
|
3503
3585
|
async function skillsCommand(options) {
|
|
3504
3586
|
const { name, agent, list, installed, uninstall, yes } = options;
|
|
@@ -3576,8 +3658,8 @@ async function installSkill(skillName, agents, skipConfirm) {
|
|
|
3576
3658
|
console.log(pc12.red(`Error: ${source.error}`));
|
|
3577
3659
|
process.exit(1);
|
|
3578
3660
|
}
|
|
3579
|
-
const skillPath =
|
|
3580
|
-
if (!
|
|
3661
|
+
const skillPath = join16(source.claudeDir, "skills", skillName);
|
|
3662
|
+
if (!fs15.existsSync(skillPath)) {
|
|
3581
3663
|
console.log(pc12.red(`Error: Skill "${skillName}" not found in source`));
|
|
3582
3664
|
console.log(pc12.gray(`Available skills: ak skills --list`));
|
|
3583
3665
|
process.exit(1);
|
|
@@ -3594,9 +3676,9 @@ async function installSkill(skillName, agents, skipConfirm) {
|
|
|
3594
3676
|
const results = [];
|
|
3595
3677
|
for (const agent of agents) {
|
|
3596
3678
|
try {
|
|
3597
|
-
const targetPath =
|
|
3598
|
-
await
|
|
3599
|
-
await
|
|
3679
|
+
const targetPath = join16(process.cwd(), AGENT_SKILL_PATHS[agent], skillName);
|
|
3680
|
+
await fs15.ensureDir(join16(process.cwd(), AGENT_SKILL_PATHS[agent]));
|
|
3681
|
+
await fs15.copy(skillPath, targetPath, { overwrite: true });
|
|
3600
3682
|
results.push({ agent, success: true });
|
|
3601
3683
|
} catch (err) {
|
|
3602
3684
|
results.push({ agent, success: false, error: err.message });
|
|
@@ -3635,8 +3717,8 @@ async function uninstallSkill(skillName, agents, skipConfirm) {
|
|
|
3635
3717
|
const results = [];
|
|
3636
3718
|
for (const agent of installedIn) {
|
|
3637
3719
|
try {
|
|
3638
|
-
const targetPath =
|
|
3639
|
-
await
|
|
3720
|
+
const targetPath = join16(process.cwd(), AGENT_SKILL_PATHS[agent], skillName);
|
|
3721
|
+
await fs15.remove(targetPath);
|
|
3640
3722
|
results.push({ agent, success: true });
|
|
3641
3723
|
} catch (err) {
|
|
3642
3724
|
results.push({ agent, success: false, error: err.message });
|
|
@@ -3671,19 +3753,19 @@ function parseAgents(agentFlag) {
|
|
|
3671
3753
|
return valid;
|
|
3672
3754
|
}
|
|
3673
3755
|
function isSkillInstalled(skillName, agent) {
|
|
3674
|
-
const skillPath =
|
|
3675
|
-
return
|
|
3756
|
+
const skillPath = join16(process.cwd(), AGENT_SKILL_PATHS[agent], skillName);
|
|
3757
|
+
return fs15.existsSync(skillPath);
|
|
3676
3758
|
}
|
|
3677
3759
|
function getInstalledSkills(agent) {
|
|
3678
|
-
const skillsDir =
|
|
3679
|
-
if (!
|
|
3760
|
+
const skillsDir = join16(process.cwd(), AGENT_SKILL_PATHS[agent]);
|
|
3761
|
+
if (!fs15.existsSync(skillsDir)) {
|
|
3680
3762
|
return [];
|
|
3681
3763
|
}
|
|
3682
3764
|
try {
|
|
3683
|
-
const items =
|
|
3765
|
+
const items = fs15.readdirSync(skillsDir);
|
|
3684
3766
|
return items.filter((item) => {
|
|
3685
|
-
const itemPath =
|
|
3686
|
-
return
|
|
3767
|
+
const itemPath = join16(skillsDir, item);
|
|
3768
|
+
return fs15.statSync(itemPath).isDirectory();
|
|
3687
3769
|
});
|
|
3688
3770
|
} catch {
|
|
3689
3771
|
return [];
|
|
@@ -3707,7 +3789,7 @@ var init_skills = __esm({
|
|
|
3707
3789
|
import cac from "cac";
|
|
3708
3790
|
import { readFileSync as readFileSync3 } from "fs";
|
|
3709
3791
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3710
|
-
import { dirname as
|
|
3792
|
+
import { dirname as dirname5, join as join18 } from "path";
|
|
3711
3793
|
import pc13 from "picocolors";
|
|
3712
3794
|
|
|
3713
3795
|
// src/cli/command-registry.ts
|
|
@@ -3763,11 +3845,11 @@ function registerCommands(cli2) {
|
|
|
3763
3845
|
}
|
|
3764
3846
|
|
|
3765
3847
|
// src/utils/version-check.ts
|
|
3766
|
-
import { join as
|
|
3848
|
+
import { join as join17 } from "path";
|
|
3767
3849
|
import { homedir as homedir2 } from "os";
|
|
3768
3850
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
3769
|
-
var CACHE_DIR =
|
|
3770
|
-
var CACHE_FILE =
|
|
3851
|
+
var CACHE_DIR = join17(homedir2(), ".thanh-kit");
|
|
3852
|
+
var CACHE_FILE = join17(CACHE_DIR, "version-check.json");
|
|
3771
3853
|
var CACHE_TTL = 7 * 24 * 60 * 60 * 1e3;
|
|
3772
3854
|
function getCachedVersionNoFetch() {
|
|
3773
3855
|
try {
|
|
@@ -3791,10 +3873,10 @@ function isNewerVersion(current, latest) {
|
|
|
3791
3873
|
|
|
3792
3874
|
// src/index.ts
|
|
3793
3875
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
3794
|
-
var __dirname2 =
|
|
3876
|
+
var __dirname2 = dirname5(__filename2);
|
|
3795
3877
|
function getVersion() {
|
|
3796
3878
|
try {
|
|
3797
|
-
const pkg = JSON.parse(readFileSync3(
|
|
3879
|
+
const pkg = JSON.parse(readFileSync3(join18(__dirname2, "..", "package.json"), "utf-8"));
|
|
3798
3880
|
return pkg.version;
|
|
3799
3881
|
} catch {
|
|
3800
3882
|
return "0.0.0";
|