@orderful/droid 0.33.1 → 0.34.1
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/CHANGELOG.md +22 -0
- package/dist/bin/droid.js +689 -102
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/repos.d.ts +21 -0
- package/dist/commands/repos.d.ts.map +1 -0
- package/dist/commands/tui/components/SettingsDetails.d.ts +2 -1
- package/dist/commands/tui/components/SettingsDetails.d.ts.map +1 -1
- package/dist/commands/tui/types.d.ts +1 -1
- package/dist/commands/tui/types.d.ts.map +1 -1
- package/dist/commands/tui/views/ReposManagementScreen.d.ts +6 -0
- package/dist/commands/tui/views/ReposManagementScreen.d.ts.map +1 -0
- package/dist/commands/tui/views/ReposViewerScreen.d.ts +5 -0
- package/dist/commands/tui/views/ReposViewerScreen.d.ts.map +1 -0
- package/dist/commands/tui.d.ts.map +1 -1
- package/dist/index.js +156 -26
- package/dist/lib/config.d.ts +34 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/types.d.ts +10 -1
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/tools/brain/skills/brain/SKILL.md +2 -2
- package/dist/tools/brain/skills/brain/references/workflows.md +10 -10
- package/dist/tools/coach/skills/coach/SKILL.md +6 -6
- package/dist/tools/codex/skills/codex/SKILL.md +5 -5
- package/dist/tools/codex/skills/codex/references/creating.md +2 -2
- package/dist/tools/codex/skills/codex/references/decisions.md +2 -2
- package/dist/tools/codex/skills/codex/references/loading.md +1 -1
- package/dist/tools/codex/skills/codex/references/topics.md +2 -2
- package/dist/tools/codex/skills/codex/scripts/git-finish-write.d.ts +1 -1
- package/dist/tools/codex/skills/codex/scripts/git-finish-write.ts +2 -2
- package/dist/tools/codex/skills/codex/scripts/git-preamble.d.ts +1 -1
- package/dist/tools/codex/skills/codex/scripts/git-preamble.ts +3 -3
- package/dist/tools/codex/skills/codex/scripts/git-start-write.d.ts +1 -1
- package/dist/tools/codex/skills/codex/scripts/git-start-write.ts +2 -2
- package/dist/tools/comments/skills/comments/SKILL.md +9 -9
- package/dist/tools/plan/skills/plan/SKILL.md +2 -2
- package/dist/tools/plan/skills/plan/references/workflows.md +2 -2
- package/dist/tools/project/skills/project/SKILL.md +1 -1
- package/dist/tools/project/skills/project/references/creating.md +2 -2
- package/dist/tools/project/skills/project/references/loading.md +1 -1
- package/dist/tools/tech-design/skills/tech-design/SKILL.md +2 -2
- package/dist/tools/tech-design/skills/tech-design/references/publish.md +3 -3
- package/dist/tools/tech-design/skills/tech-design/references/start.md +29 -3
- package/dist/tools/tech-design/skills/tech-design/references/think.md +1 -1
- package/dist/tools/wrapup/skills/wrapup/references/subagent-prompts.md +3 -3
- package/package.json +1 -1
- package/src/bin/droid.ts +39 -0
- package/src/commands/config.ts +14 -1
- package/src/commands/repos.ts +185 -0
- package/src/commands/tui/components/SettingsDetails.tsx +42 -13
- package/src/commands/tui/types.ts +1 -1
- package/src/commands/tui/views/ReposManagementScreen.tsx +291 -0
- package/src/commands/tui/views/ReposViewerScreen.tsx +49 -0
- package/src/commands/tui/views/SkillConfigScreen.tsx +2 -2
- package/src/commands/tui.tsx +51 -4
- package/src/lib/config.test.ts +228 -1
- package/src/lib/config.ts +205 -4
- package/src/lib/types.ts +13 -1
- package/src/tools/brain/skills/brain/SKILL.md +2 -2
- package/src/tools/brain/skills/brain/references/workflows.md +10 -10
- package/src/tools/coach/skills/coach/SKILL.md +6 -6
- package/src/tools/codex/skills/codex/SKILL.md +5 -5
- package/src/tools/codex/skills/codex/references/creating.md +2 -2
- package/src/tools/codex/skills/codex/references/decisions.md +2 -2
- package/src/tools/codex/skills/codex/references/loading.md +1 -1
- package/src/tools/codex/skills/codex/references/topics.md +2 -2
- package/src/tools/codex/skills/codex/scripts/git-finish-write.ts +2 -2
- package/src/tools/codex/skills/codex/scripts/git-preamble.ts +3 -3
- package/src/tools/codex/skills/codex/scripts/git-start-write.ts +2 -2
- package/src/tools/comments/skills/comments/SKILL.md +9 -9
- package/src/tools/plan/skills/plan/SKILL.md +2 -2
- package/src/tools/plan/skills/plan/references/workflows.md +2 -2
- package/src/tools/project/skills/project/SKILL.md +1 -1
- package/src/tools/project/skills/project/references/creating.md +2 -2
- package/src/tools/project/skills/project/references/loading.md +1 -1
- package/src/tools/tech-design/skills/tech-design/SKILL.md +2 -2
- package/src/tools/tech-design/skills/tech-design/references/publish.md +3 -3
- package/src/tools/tech-design/skills/tech-design/references/start.md +29 -3
- package/src/tools/tech-design/skills/tech-design/references/think.md +1 -1
- package/src/tools/wrapup/skills/wrapup/references/subagent-prompts.md +3 -3
package/dist/bin/droid.js
CHANGED
|
@@ -12,7 +12,13 @@ import { join as join8 } from "path";
|
|
|
12
12
|
import { homedir as homedir4 } from "os";
|
|
13
13
|
|
|
14
14
|
// src/lib/config.ts
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
existsSync,
|
|
17
|
+
mkdirSync,
|
|
18
|
+
readFileSync,
|
|
19
|
+
readdirSync,
|
|
20
|
+
writeFileSync
|
|
21
|
+
} from "fs";
|
|
16
22
|
import { homedir } from "os";
|
|
17
23
|
import { join } from "path";
|
|
18
24
|
import YAML from "yaml";
|
|
@@ -68,6 +74,54 @@ function migrateConfig(config) {
|
|
|
68
74
|
platforms: config.platforms ?? {}
|
|
69
75
|
};
|
|
70
76
|
}
|
|
77
|
+
function migrateToolConfigs(config) {
|
|
78
|
+
const skillsDir = join(CONFIG_DIR, "skills");
|
|
79
|
+
if (!existsSync(skillsDir)) {
|
|
80
|
+
if (!config.migrations) {
|
|
81
|
+
config.migrations = {};
|
|
82
|
+
}
|
|
83
|
+
if (!config.migrations.tools_consolidated) {
|
|
84
|
+
config.migrations.tools_consolidated = true;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
let migrated = false;
|
|
90
|
+
try {
|
|
91
|
+
const entries = readdirSync(skillsDir, { withFileTypes: true });
|
|
92
|
+
for (const entry of entries) {
|
|
93
|
+
if (!entry.isDirectory()) continue;
|
|
94
|
+
const skillName = entry.name;
|
|
95
|
+
const overridesPath = join(skillsDir, skillName, "overrides.yaml");
|
|
96
|
+
if (!existsSync(overridesPath)) continue;
|
|
97
|
+
try {
|
|
98
|
+
const content = readFileSync(overridesPath, "utf-8");
|
|
99
|
+
const overrides = YAML.parse(content);
|
|
100
|
+
if (overrides && Object.keys(overrides).length > 0) {
|
|
101
|
+
if (!config.tools) {
|
|
102
|
+
config.tools = {};
|
|
103
|
+
}
|
|
104
|
+
if (!config.tools[skillName]) {
|
|
105
|
+
config.tools[skillName] = overrides;
|
|
106
|
+
migrated = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (!config.migrations) {
|
|
114
|
+
config.migrations = {};
|
|
115
|
+
}
|
|
116
|
+
if (!config.migrations.tools_consolidated) {
|
|
117
|
+
config.migrations.tools_consolidated = true;
|
|
118
|
+
migrated = true;
|
|
119
|
+
}
|
|
120
|
+
return migrated;
|
|
121
|
+
} catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
71
125
|
function ensureConfigDir() {
|
|
72
126
|
if (!existsSync(CONFIG_DIR)) {
|
|
73
127
|
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
@@ -84,9 +138,10 @@ function loadConfig() {
|
|
|
84
138
|
try {
|
|
85
139
|
const content = readFileSync(CONFIG_FILE, "utf-8");
|
|
86
140
|
const rawConfig = YAML.parse(content);
|
|
87
|
-
const
|
|
141
|
+
const needsLegacyMigration = "ai_tool" in rawConfig && !("platform" in rawConfig);
|
|
88
142
|
const config = migrateConfig(rawConfig);
|
|
89
|
-
|
|
143
|
+
const needsToolMigration = migrateToolConfigs(config);
|
|
144
|
+
if (needsLegacyMigration || needsToolMigration) {
|
|
90
145
|
saveConfig(config);
|
|
91
146
|
}
|
|
92
147
|
return config;
|
|
@@ -140,6 +195,11 @@ function getSkillOverridesPath(skillName) {
|
|
|
140
195
|
return join(CONFIG_DIR, "skills", normalizedName, "overrides.yaml");
|
|
141
196
|
}
|
|
142
197
|
function loadSkillOverrides(skillName) {
|
|
198
|
+
const normalizedName = normalizeSkillNameForConfig(skillName);
|
|
199
|
+
const toolSettings = getToolSettings(normalizedName);
|
|
200
|
+
if (Object.keys(toolSettings).length > 0) {
|
|
201
|
+
return toolSettings;
|
|
202
|
+
}
|
|
143
203
|
const overridesPath = getSkillOverridesPath(skillName);
|
|
144
204
|
if (!existsSync(overridesPath)) {
|
|
145
205
|
return {};
|
|
@@ -161,6 +221,18 @@ function saveSkillOverrides(skillName, overrides) {
|
|
|
161
221
|
const content = YAML.stringify(overrides, { indent: 2 });
|
|
162
222
|
writeFileSync(overridesPath, content, "utf-8");
|
|
163
223
|
}
|
|
224
|
+
function getToolSettings(name) {
|
|
225
|
+
const config = loadConfig();
|
|
226
|
+
return config.tools?.[name] ?? {};
|
|
227
|
+
}
|
|
228
|
+
function setToolSettings(name, settings) {
|
|
229
|
+
const config = loadConfig();
|
|
230
|
+
if (!config.tools) {
|
|
231
|
+
config.tools = {};
|
|
232
|
+
}
|
|
233
|
+
config.tools[name] = settings;
|
|
234
|
+
saveConfig(config);
|
|
235
|
+
}
|
|
164
236
|
function getAutoUpdateConfig() {
|
|
165
237
|
const config = loadConfig();
|
|
166
238
|
return {
|
|
@@ -177,11 +249,56 @@ function setAutoUpdateConfig(updates) {
|
|
|
177
249
|
};
|
|
178
250
|
saveConfig(config);
|
|
179
251
|
}
|
|
252
|
+
function expandTilde(path) {
|
|
253
|
+
if (path.startsWith("~/")) {
|
|
254
|
+
return join(homedir(), path.slice(2));
|
|
255
|
+
}
|
|
256
|
+
return path;
|
|
257
|
+
}
|
|
258
|
+
function getRepos() {
|
|
259
|
+
const config = loadConfig();
|
|
260
|
+
return config.repos ?? [];
|
|
261
|
+
}
|
|
262
|
+
function getRepo(name) {
|
|
263
|
+
const repos2 = getRepos();
|
|
264
|
+
return repos2.find((repo) => repo.name === name);
|
|
265
|
+
}
|
|
266
|
+
function getRepoPath(name) {
|
|
267
|
+
const repo = getRepo(name);
|
|
268
|
+
if (!repo) {
|
|
269
|
+
return void 0;
|
|
270
|
+
}
|
|
271
|
+
return expandTilde(repo.path);
|
|
272
|
+
}
|
|
273
|
+
function addRepo(repo) {
|
|
274
|
+
const config = loadConfig();
|
|
275
|
+
const repos2 = config.repos ?? [];
|
|
276
|
+
const existingIndex = repos2.findIndex((r) => r.name === repo.name);
|
|
277
|
+
if (existingIndex >= 0) {
|
|
278
|
+
repos2[existingIndex] = repo;
|
|
279
|
+
} else {
|
|
280
|
+
repos2.push(repo);
|
|
281
|
+
}
|
|
282
|
+
config.repos = repos2;
|
|
283
|
+
saveConfig(config);
|
|
284
|
+
}
|
|
285
|
+
function removeRepo(name) {
|
|
286
|
+
const config = loadConfig();
|
|
287
|
+
const repos2 = config.repos ?? [];
|
|
288
|
+
const existingIndex = repos2.findIndex((r) => r.name === name);
|
|
289
|
+
if (existingIndex >= 0) {
|
|
290
|
+
repos2.splice(existingIndex, 1);
|
|
291
|
+
config.repos = repos2;
|
|
292
|
+
saveConfig(config);
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
180
297
|
|
|
181
298
|
// src/lib/skills.ts
|
|
182
299
|
import {
|
|
183
300
|
existsSync as existsSync6,
|
|
184
|
-
readdirSync as
|
|
301
|
+
readdirSync as readdirSync5,
|
|
185
302
|
readFileSync as readFileSync6,
|
|
186
303
|
mkdirSync as mkdirSync4,
|
|
187
304
|
writeFileSync as writeFileSync4,
|
|
@@ -192,7 +309,7 @@ import { fileURLToPath as fileURLToPath4 } from "url";
|
|
|
192
309
|
import YAML4 from "yaml";
|
|
193
310
|
|
|
194
311
|
// src/lib/agents.ts
|
|
195
|
-
import { existsSync as existsSync4, readdirSync as
|
|
312
|
+
import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2, unlinkSync, mkdirSync as mkdirSync2 } from "fs";
|
|
196
313
|
import { join as join5, dirname as dirname3 } from "path";
|
|
197
314
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
198
315
|
import YAML3 from "yaml";
|
|
@@ -262,7 +379,7 @@ function getActivePlatforms(config) {
|
|
|
262
379
|
}
|
|
263
380
|
|
|
264
381
|
// src/lib/tools.ts
|
|
265
|
-
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3 } from "fs";
|
|
382
|
+
import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "fs";
|
|
266
383
|
import { join as join4, dirname as dirname2 } from "path";
|
|
267
384
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
268
385
|
import YAML2 from "yaml";
|
|
@@ -358,7 +475,7 @@ function getBundledTools() {
|
|
|
358
475
|
if (!existsSync3(BUNDLED_TOOLS_DIR)) {
|
|
359
476
|
return [];
|
|
360
477
|
}
|
|
361
|
-
const toolDirs =
|
|
478
|
+
const toolDirs = readdirSync2(BUNDLED_TOOLS_DIR, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
362
479
|
const tools = [];
|
|
363
480
|
for (const toolName of toolDirs) {
|
|
364
481
|
const manifest = loadToolManifest(join4(BUNDLED_TOOLS_DIR, toolName));
|
|
@@ -561,7 +678,7 @@ import {
|
|
|
561
678
|
mkdirSync as mkdirSync3,
|
|
562
679
|
renameSync,
|
|
563
680
|
rmSync,
|
|
564
|
-
readdirSync as
|
|
681
|
+
readdirSync as readdirSync4,
|
|
565
682
|
readFileSync as readFileSync5,
|
|
566
683
|
writeFileSync as writeFileSync3
|
|
567
684
|
} from "fs";
|
|
@@ -617,7 +734,7 @@ function createPlatformSyncMigration(version2) {
|
|
|
617
734
|
if (!existsSync5(skillsPath)) continue;
|
|
618
735
|
config.platform = platformKey;
|
|
619
736
|
const trackedTools = getPlatformTools(config);
|
|
620
|
-
const installedDirs =
|
|
737
|
+
const installedDirs = readdirSync4(skillsPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
621
738
|
for (const skillName of installedDirs) {
|
|
622
739
|
const normalizedName = skillName.replace(/^droid-/, "");
|
|
623
740
|
const isTracked = trackedTools[skillName] || trackedTools[`droid-${normalizedName}`] || trackedTools[normalizedName];
|
|
@@ -705,7 +822,7 @@ function createOpenCodeSkillsPathMigration(version2) {
|
|
|
705
822
|
}
|
|
706
823
|
return;
|
|
707
824
|
}
|
|
708
|
-
const skillDirs =
|
|
825
|
+
const skillDirs = readdirSync4(oldSkillsPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
709
826
|
for (const skillName of skillDirs) {
|
|
710
827
|
const oldSkillDir = join6(oldSkillsPath, skillName);
|
|
711
828
|
const newSkillDir = join6(newSkillsPath, skillName);
|
|
@@ -720,7 +837,7 @@ function createOpenCodeSkillsPathMigration(version2) {
|
|
|
720
837
|
}
|
|
721
838
|
}
|
|
722
839
|
try {
|
|
723
|
-
const remaining =
|
|
840
|
+
const remaining = readdirSync4(oldSkillsPath);
|
|
724
841
|
if (remaining.length === 0) {
|
|
725
842
|
rmSync(oldSkillsPath, { recursive: true });
|
|
726
843
|
}
|
|
@@ -750,7 +867,7 @@ function createClaudeCodeCommandCleanupMigration(version2) {
|
|
|
750
867
|
}
|
|
751
868
|
}
|
|
752
869
|
}
|
|
753
|
-
const commandFiles =
|
|
870
|
+
const commandFiles = readdirSync4(commandsPath, { withFileTypes: true }).filter((dirent) => dirent.isFile() && dirent.name.endsWith(".md")).map((dirent) => dirent.name);
|
|
754
871
|
for (const file of commandFiles) {
|
|
755
872
|
const commandName = file.replace(".md", "");
|
|
756
873
|
if (!aliasCommands.has(commandName)) {
|
|
@@ -828,7 +945,7 @@ function createUnifiedSkillsPathMigration(version2) {
|
|
|
828
945
|
if (!existsSync5(unifiedSkillsPath)) {
|
|
829
946
|
mkdirSync3(unifiedSkillsPath, { recursive: true });
|
|
830
947
|
}
|
|
831
|
-
const skillDirs =
|
|
948
|
+
const skillDirs = readdirSync4(oldOpenCodeSkillsPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
832
949
|
for (const skillName of skillDirs) {
|
|
833
950
|
const sourcePath = join6(oldOpenCodeSkillsPath, skillName);
|
|
834
951
|
const destPath = join6(unifiedSkillsPath, skillName);
|
|
@@ -848,7 +965,7 @@ function createUnifiedSkillsPathMigration(version2) {
|
|
|
848
965
|
}
|
|
849
966
|
function copyDirRecursive(src, dest) {
|
|
850
967
|
mkdirSync3(dest, { recursive: true });
|
|
851
|
-
const entries =
|
|
968
|
+
const entries = readdirSync4(src, { withFileTypes: true });
|
|
852
969
|
for (const entry of entries) {
|
|
853
970
|
const srcPath = join6(src, entry.name);
|
|
854
971
|
const destPath = join6(dest, entry.name);
|
|
@@ -1072,7 +1189,7 @@ function findSkillPath(skillName) {
|
|
|
1072
1189
|
if (!existsSync6(BUNDLED_SKILLS_DIR)) {
|
|
1073
1190
|
return null;
|
|
1074
1191
|
}
|
|
1075
|
-
const toolDirs =
|
|
1192
|
+
const toolDirs = readdirSync5(BUNDLED_SKILLS_DIR, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
1076
1193
|
for (const toolName of toolDirs) {
|
|
1077
1194
|
const skillsDir = join7(BUNDLED_SKILLS_DIR, toolName, "skills");
|
|
1078
1195
|
if (!existsSync6(skillsDir)) continue;
|
|
@@ -1090,12 +1207,12 @@ function getBundledSkills() {
|
|
|
1090
1207
|
if (!existsSync6(BUNDLED_SKILLS_DIR)) {
|
|
1091
1208
|
return [];
|
|
1092
1209
|
}
|
|
1093
|
-
const toolDirs =
|
|
1210
|
+
const toolDirs = readdirSync5(BUNDLED_SKILLS_DIR, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
1094
1211
|
const skills = [];
|
|
1095
1212
|
for (const toolName of toolDirs) {
|
|
1096
1213
|
const skillsDir = join7(BUNDLED_SKILLS_DIR, toolName, "skills");
|
|
1097
1214
|
if (!existsSync6(skillsDir)) continue;
|
|
1098
|
-
const skillSubdirs =
|
|
1215
|
+
const skillSubdirs = readdirSync5(skillsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
1099
1216
|
for (const skillName of skillSubdirs) {
|
|
1100
1217
|
const manifest = loadSkillManifest(join7(skillsDir, skillName));
|
|
1101
1218
|
if (manifest) {
|
|
@@ -1257,7 +1374,7 @@ function installSkill(skillName) {
|
|
|
1257
1374
|
if (!isAlreadyInstalled) {
|
|
1258
1375
|
const toolName2 = basename(toolDir);
|
|
1259
1376
|
if (existsSync6(commandsSource)) {
|
|
1260
|
-
const commandFiles =
|
|
1377
|
+
const commandFiles = readdirSync5(commandsSource).filter(
|
|
1261
1378
|
(f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md"
|
|
1262
1379
|
);
|
|
1263
1380
|
for (const file of commandFiles) {
|
|
@@ -1275,7 +1392,7 @@ function installSkill(skillName) {
|
|
|
1275
1392
|
}
|
|
1276
1393
|
}
|
|
1277
1394
|
if (existsSync6(agentsSource)) {
|
|
1278
|
-
const agentFiles =
|
|
1395
|
+
const agentFiles = readdirSync5(agentsSource, { withFileTypes: true }).filter((dirent) => dirent.isFile() && dirent.name.endsWith(".md")).map((dirent) => dirent.name.replace(".md", ""));
|
|
1279
1396
|
for (const agentName of agentFiles) {
|
|
1280
1397
|
if (isAgentInstalled(agentName)) {
|
|
1281
1398
|
return {
|
|
@@ -1304,7 +1421,7 @@ function installSkill(skillName) {
|
|
|
1304
1421
|
if (!existsSync6(targetReferencesDir)) {
|
|
1305
1422
|
mkdirSync4(targetReferencesDir, { recursive: true });
|
|
1306
1423
|
}
|
|
1307
|
-
const referenceFiles =
|
|
1424
|
+
const referenceFiles = readdirSync5(referencesSource).filter(
|
|
1308
1425
|
(f) => f.endsWith(".md")
|
|
1309
1426
|
);
|
|
1310
1427
|
for (const file of referenceFiles) {
|
|
@@ -1320,7 +1437,7 @@ function installSkill(skillName) {
|
|
|
1320
1437
|
if (!existsSync6(targetScriptsDir)) {
|
|
1321
1438
|
mkdirSync4(targetScriptsDir, { recursive: true });
|
|
1322
1439
|
}
|
|
1323
|
-
const scriptFiles =
|
|
1440
|
+
const scriptFiles = readdirSync5(scriptsSource).filter(
|
|
1324
1441
|
(f) => f.endsWith(".ts") || f.endsWith(".js") || f.endsWith(".py")
|
|
1325
1442
|
);
|
|
1326
1443
|
for (const file of scriptFiles) {
|
|
@@ -1333,7 +1450,7 @@ function installSkill(skillName) {
|
|
|
1333
1450
|
const activePlatforms = getActivePlatforms(config);
|
|
1334
1451
|
const targetPlatforms = activePlatforms.length > 0 ? activePlatforms : [config.platform];
|
|
1335
1452
|
if (existsSync6(commandsSource)) {
|
|
1336
|
-
const commandFiles =
|
|
1453
|
+
const commandFiles = readdirSync5(commandsSource).filter(
|
|
1337
1454
|
(f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md"
|
|
1338
1455
|
);
|
|
1339
1456
|
for (const platform of targetPlatforms) {
|
|
@@ -1359,7 +1476,7 @@ function installSkill(skillName) {
|
|
|
1359
1476
|
}
|
|
1360
1477
|
const installedAgents = [];
|
|
1361
1478
|
if (existsSync6(agentsSource)) {
|
|
1362
|
-
const agentFiles =
|
|
1479
|
+
const agentFiles = readdirSync5(agentsSource, { withFileTypes: true }).filter((dirent) => dirent.isFile() && dirent.name.endsWith(".md")).map((dirent) => dirent.name.replace(".md", ""));
|
|
1363
1480
|
for (const agentName of agentFiles) {
|
|
1364
1481
|
const agentPath = join7(agentsSource, `${agentName}.md`);
|
|
1365
1482
|
let anySuccess = false;
|
|
@@ -1416,7 +1533,7 @@ function uninstallSkill(skillName) {
|
|
|
1416
1533
|
const skillPath = findSkillPath(skillName);
|
|
1417
1534
|
const commandsSource = skillPath ? join7(skillPath.toolDir, "commands") : null;
|
|
1418
1535
|
if (commandsSource && existsSync6(commandsSource)) {
|
|
1419
|
-
const commandFiles =
|
|
1536
|
+
const commandFiles = readdirSync5(commandsSource).filter(
|
|
1420
1537
|
(f) => f.endsWith(".md") && f.toLowerCase() !== "readme.md"
|
|
1421
1538
|
);
|
|
1422
1539
|
for (const platform of targetPlatforms) {
|
|
@@ -1438,7 +1555,7 @@ function uninstallSkill(skillName) {
|
|
|
1438
1555
|
}
|
|
1439
1556
|
const agentsSource = skillPath ? join7(skillPath.toolDir, "agents") : null;
|
|
1440
1557
|
if (agentsSource && existsSync6(agentsSource)) {
|
|
1441
|
-
const agentFiles =
|
|
1558
|
+
const agentFiles = readdirSync5(agentsSource, { withFileTypes: true }).filter((dirent) => dirent.isFile() && dirent.name.endsWith(".md")).map((dirent) => dirent.name.replace(".md", ""));
|
|
1442
1559
|
for (const agentName of agentFiles) {
|
|
1443
1560
|
agentsToRemove.add(agentName);
|
|
1444
1561
|
}
|
|
@@ -1675,6 +1792,11 @@ function getToolConfig(toolName) {
|
|
|
1675
1792
|
}
|
|
1676
1793
|
async function configCommand(tool, options) {
|
|
1677
1794
|
if (tool) {
|
|
1795
|
+
console.log(
|
|
1796
|
+
chalk3.yellow(
|
|
1797
|
+
`Warning: 'droid config <tool>' is deprecated. Use 'droid config --get tools.${tool}' instead.`
|
|
1798
|
+
)
|
|
1799
|
+
);
|
|
1678
1800
|
const toolConfig = getToolConfig(tool);
|
|
1679
1801
|
console.log(JSON.stringify(toolConfig, null, 2));
|
|
1680
1802
|
return;
|
|
@@ -1714,6 +1836,11 @@ async function configCommand(tool, options) {
|
|
|
1714
1836
|
process.exit(1);
|
|
1715
1837
|
}
|
|
1716
1838
|
const [, key, rawValue] = match;
|
|
1839
|
+
if (key === "repos" || key.startsWith("repos.")) {
|
|
1840
|
+
console.error(chalk3.red("Cannot set repos via --set."));
|
|
1841
|
+
console.log(chalk3.gray("Use: droid repos add/remove"));
|
|
1842
|
+
process.exit(1);
|
|
1843
|
+
}
|
|
1717
1844
|
let value;
|
|
1718
1845
|
try {
|
|
1719
1846
|
value = JSON.parse(rawValue);
|
|
@@ -2092,8 +2219,8 @@ async function updateCommand(tool, options) {
|
|
|
2092
2219
|
}
|
|
2093
2220
|
|
|
2094
2221
|
// src/commands/tui.tsx
|
|
2095
|
-
import { render, Box as
|
|
2096
|
-
import { useState as
|
|
2222
|
+
import { render, Box as Box15, Text as Text16, useInput as useInput9, useApp as useApp2 } from "ink";
|
|
2223
|
+
import { useState as useState10, useEffect } from "react";
|
|
2097
2224
|
|
|
2098
2225
|
// src/commands/tui/constants.ts
|
|
2099
2226
|
var colors = {
|
|
@@ -2289,48 +2416,89 @@ var PLATFORM_LABELS2 = {
|
|
|
2289
2416
|
function SettingsDetails({
|
|
2290
2417
|
isFocused,
|
|
2291
2418
|
detectedPlatforms,
|
|
2419
|
+
selectedAction,
|
|
2292
2420
|
onRedetect: _onRedetect
|
|
2293
2421
|
// TODO: Add re-detect button when no platforms found
|
|
2294
2422
|
}) {
|
|
2295
2423
|
const config = loadConfig();
|
|
2296
2424
|
const autoUpdateConfig = getAutoUpdateConfig();
|
|
2425
|
+
const repos2 = getRepos();
|
|
2297
2426
|
const platformsText = detectedPlatforms.length > 0 ? detectedPlatforms.map((p) => PLATFORM_LABELS2[p]).join(", ") : "None detected";
|
|
2298
2427
|
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingLeft: 2, flexGrow: 1, children: [
|
|
2299
2428
|
/* @__PURE__ */ jsx5(Text5, { color: colors.text, bold: true, children: "Settings" }),
|
|
2300
2429
|
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
2430
|
+
/* @__PURE__ */ jsx5(Text5, { color: colors.textDim, bold: true, children: "Global" }),
|
|
2301
2431
|
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
2302
|
-
/* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: "
|
|
2432
|
+
/* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: " Detected platforms: " }),
|
|
2303
2433
|
/* @__PURE__ */ jsx5(Text5, { color: colors.text, children: platformsText })
|
|
2304
2434
|
] }),
|
|
2305
2435
|
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
2306
|
-
/* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: "Your @mention: " }),
|
|
2436
|
+
/* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: " Your @mention: " }),
|
|
2307
2437
|
/* @__PURE__ */ jsx5(Text5, { color: colors.text, children: config.user_mention })
|
|
2308
2438
|
] }),
|
|
2309
2439
|
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
2310
|
-
/* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: "Auto-update tools: " }),
|
|
2440
|
+
/* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: " Auto-update tools: " }),
|
|
2311
2441
|
/* @__PURE__ */ jsx5(Text5, { color: colors.text, children: autoUpdateConfig.tools ? "enabled" : "disabled" })
|
|
2312
2442
|
] }),
|
|
2313
2443
|
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
2314
|
-
/* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: "Auto-update app: " }),
|
|
2444
|
+
/* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: " Auto-update app: " }),
|
|
2315
2445
|
/* @__PURE__ */ jsx5(Text5, { color: colors.text, children: autoUpdateConfig.app ? "enabled" : "disabled" })
|
|
2316
2446
|
] })
|
|
2317
2447
|
] }),
|
|
2318
|
-
/* @__PURE__ */
|
|
2319
|
-
|
|
2320
|
-
Text5,
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2448
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
2449
|
+
/* @__PURE__ */ jsx5(Text5, { color: colors.textDim, bold: true, children: "Repos" }),
|
|
2450
|
+
repos2.length === 0 ? /* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: " No repos configured" }) : /* @__PURE__ */ jsxs5(Text5, { color: colors.textDim, children: [
|
|
2451
|
+
" ",
|
|
2452
|
+
repos2.map((r) => r.name).join(", "),
|
|
2453
|
+
" (",
|
|
2454
|
+
repos2.length,
|
|
2455
|
+
" total)"
|
|
2456
|
+
] })
|
|
2457
|
+
] }),
|
|
2458
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: "Config: ~/.droid/config.yaml" }) }),
|
|
2459
|
+
isFocused && /* @__PURE__ */ jsxs5(Box5, { marginTop: 2, flexDirection: "row", gap: 2, children: [
|
|
2460
|
+
/* @__PURE__ */ jsxs5(
|
|
2461
|
+
Text5,
|
|
2462
|
+
{
|
|
2463
|
+
backgroundColor: selectedAction === 0 ? colors.primary : void 0,
|
|
2464
|
+
color: selectedAction === 0 ? "#ffffff" : colors.textDim,
|
|
2465
|
+
bold: selectedAction === 0,
|
|
2466
|
+
children: [
|
|
2467
|
+
" ",
|
|
2468
|
+
"Edit Config",
|
|
2469
|
+
" "
|
|
2470
|
+
]
|
|
2471
|
+
}
|
|
2472
|
+
),
|
|
2473
|
+
/* @__PURE__ */ jsxs5(
|
|
2474
|
+
Text5,
|
|
2475
|
+
{
|
|
2476
|
+
backgroundColor: selectedAction === 1 ? colors.primary : void 0,
|
|
2477
|
+
color: selectedAction === 1 ? "#ffffff" : colors.textDim,
|
|
2478
|
+
bold: selectedAction === 1,
|
|
2479
|
+
children: [
|
|
2480
|
+
" ",
|
|
2481
|
+
"View Repos",
|
|
2482
|
+
" "
|
|
2483
|
+
]
|
|
2484
|
+
}
|
|
2485
|
+
),
|
|
2486
|
+
/* @__PURE__ */ jsxs5(
|
|
2487
|
+
Text5,
|
|
2488
|
+
{
|
|
2489
|
+
backgroundColor: selectedAction === 2 ? colors.primary : void 0,
|
|
2490
|
+
color: selectedAction === 2 ? "#ffffff" : colors.textDim,
|
|
2491
|
+
bold: selectedAction === 2,
|
|
2492
|
+
children: [
|
|
2493
|
+
" ",
|
|
2494
|
+
"Manage Repos",
|
|
2495
|
+
" "
|
|
2496
|
+
]
|
|
2497
|
+
}
|
|
2498
|
+
)
|
|
2499
|
+
] }),
|
|
2500
|
+
isFocused && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: "\u2190\u2192 select \xB7 enter confirm \xB7 esc back" }) }),
|
|
2501
|
+
!isFocused && /* @__PURE__ */ jsx5(Box5, { marginTop: 2, children: /* @__PURE__ */ jsx5(Text5, { color: colors.textDim, children: "press enter for options" }) })
|
|
2334
2502
|
] });
|
|
2335
2503
|
}
|
|
2336
2504
|
|
|
@@ -3066,7 +3234,7 @@ function SkillConfigScreen({ skill, onComplete, onCancel }) {
|
|
|
3066
3234
|
const [selectOptionIndex, setSelectOptionIndex] = useState6(0);
|
|
3067
3235
|
const totalItems = configKeys.length + 1;
|
|
3068
3236
|
const handleSave = () => {
|
|
3069
|
-
|
|
3237
|
+
setToolSettings(skill.name, values);
|
|
3070
3238
|
onComplete();
|
|
3071
3239
|
};
|
|
3072
3240
|
const handleSubmitEdit = () => {
|
|
@@ -3266,12 +3434,250 @@ function SkillConfigScreen({ skill, onComplete, onCancel }) {
|
|
|
3266
3434
|
] });
|
|
3267
3435
|
}
|
|
3268
3436
|
|
|
3437
|
+
// src/commands/tui/views/ReposManagementScreen.tsx
|
|
3438
|
+
import { Box as Box13, Text as Text14, useInput as useInput7 } from "ink";
|
|
3439
|
+
import TextInput3 from "ink-text-input";
|
|
3440
|
+
import { useState as useState7 } from "react";
|
|
3441
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3442
|
+
function ReposManagementScreen({ onComplete: _onComplete, onCancel }) {
|
|
3443
|
+
const [repos2, setRepos] = useState7(() => getRepos());
|
|
3444
|
+
const [selectedIndex, setSelectedIndex] = useState7(0);
|
|
3445
|
+
const [screen, setScreen] = useState7("list");
|
|
3446
|
+
const [message, setMessage] = useState7(null);
|
|
3447
|
+
const [newRepoName, setNewRepoName] = useState7("");
|
|
3448
|
+
const [newRepoPath, setNewRepoPath] = useState7("");
|
|
3449
|
+
const [newRepoDesc, setNewRepoDesc] = useState7("");
|
|
3450
|
+
const [repoToDelete, setRepoToDelete] = useState7(null);
|
|
3451
|
+
const handleAddRepo = () => {
|
|
3452
|
+
if (!newRepoName || !newRepoPath) {
|
|
3453
|
+
setMessage({ text: "Name and path are required", type: "error" });
|
|
3454
|
+
return;
|
|
3455
|
+
}
|
|
3456
|
+
const newRepo = {
|
|
3457
|
+
name: newRepoName,
|
|
3458
|
+
path: newRepoPath,
|
|
3459
|
+
description: newRepoDesc || void 0
|
|
3460
|
+
};
|
|
3461
|
+
addRepo(newRepo);
|
|
3462
|
+
setRepos(getRepos());
|
|
3463
|
+
setMessage({ text: `Added ${newRepoName}`, type: "success" });
|
|
3464
|
+
setNewRepoName("");
|
|
3465
|
+
setNewRepoPath("");
|
|
3466
|
+
setNewRepoDesc("");
|
|
3467
|
+
setScreen("list");
|
|
3468
|
+
};
|
|
3469
|
+
const handleDeleteRepo = (repoName) => {
|
|
3470
|
+
removeRepo(repoName);
|
|
3471
|
+
setRepos(getRepos());
|
|
3472
|
+
setMessage({ text: `Removed ${repoName}`, type: "success" });
|
|
3473
|
+
setRepoToDelete(null);
|
|
3474
|
+
setScreen("list");
|
|
3475
|
+
if (selectedIndex >= repos2.length - 1) {
|
|
3476
|
+
setSelectedIndex(Math.max(0, repos2.length - 2));
|
|
3477
|
+
}
|
|
3478
|
+
};
|
|
3479
|
+
useInput7((input, key) => {
|
|
3480
|
+
if (message) setMessage(null);
|
|
3481
|
+
if (key.escape) {
|
|
3482
|
+
onCancel();
|
|
3483
|
+
return;
|
|
3484
|
+
}
|
|
3485
|
+
if (key.upArrow) {
|
|
3486
|
+
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
3487
|
+
}
|
|
3488
|
+
if (key.downArrow) {
|
|
3489
|
+
const maxIndex = repos2.length;
|
|
3490
|
+
setSelectedIndex((prev) => Math.min(maxIndex, prev + 1));
|
|
3491
|
+
}
|
|
3492
|
+
if (key.return) {
|
|
3493
|
+
if (selectedIndex === repos2.length) {
|
|
3494
|
+
setScreen("add-name");
|
|
3495
|
+
} else if (selectedIndex < repos2.length) {
|
|
3496
|
+
setRepoToDelete(repos2[selectedIndex].name);
|
|
3497
|
+
setScreen("confirm-delete");
|
|
3498
|
+
}
|
|
3499
|
+
}
|
|
3500
|
+
}, { isActive: screen === "list" });
|
|
3501
|
+
useInput7((input, key) => {
|
|
3502
|
+
if (key.escape) {
|
|
3503
|
+
setNewRepoName("");
|
|
3504
|
+
setScreen("list");
|
|
3505
|
+
}
|
|
3506
|
+
}, { isActive: screen === "add-name" });
|
|
3507
|
+
useInput7((input, key) => {
|
|
3508
|
+
if (key.escape) {
|
|
3509
|
+
setNewRepoPath("");
|
|
3510
|
+
setScreen("add-name");
|
|
3511
|
+
}
|
|
3512
|
+
}, { isActive: screen === "add-path" });
|
|
3513
|
+
useInput7((input, key) => {
|
|
3514
|
+
if (key.escape) {
|
|
3515
|
+
setNewRepoDesc("");
|
|
3516
|
+
setScreen("add-path");
|
|
3517
|
+
}
|
|
3518
|
+
}, { isActive: screen === "add-desc" });
|
|
3519
|
+
useInput7((input, key) => {
|
|
3520
|
+
if (key.escape || input === "n") {
|
|
3521
|
+
setRepoToDelete(null);
|
|
3522
|
+
setScreen("list");
|
|
3523
|
+
}
|
|
3524
|
+
if (input === "y" && repoToDelete) {
|
|
3525
|
+
handleDeleteRepo(repoToDelete);
|
|
3526
|
+
}
|
|
3527
|
+
}, { isActive: screen === "confirm-delete" });
|
|
3528
|
+
if (screen === "add-name") {
|
|
3529
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 2, children: [
|
|
3530
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.text, bold: true, children: "Add Repository" }),
|
|
3531
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
|
|
3532
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: "Repository name: " }),
|
|
3533
|
+
/* @__PURE__ */ jsx14(
|
|
3534
|
+
TextInput3,
|
|
3535
|
+
{
|
|
3536
|
+
value: newRepoName,
|
|
3537
|
+
onChange: setNewRepoName,
|
|
3538
|
+
onSubmit: () => {
|
|
3539
|
+
if (newRepoName) {
|
|
3540
|
+
setScreen("add-path");
|
|
3541
|
+
}
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
)
|
|
3545
|
+
] }),
|
|
3546
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: "esc cancel" }) })
|
|
3547
|
+
] });
|
|
3548
|
+
}
|
|
3549
|
+
if (screen === "add-path") {
|
|
3550
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 2, children: [
|
|
3551
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.text, bold: true, children: "Add Repository" }),
|
|
3552
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
|
|
3553
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: "Name: " }),
|
|
3554
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.text, children: newRepoName })
|
|
3555
|
+
] }),
|
|
3556
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
|
|
3557
|
+
/* @__PURE__ */ jsxs13(Text14, { color: colors.textDim, children: [
|
|
3558
|
+
"Path (e.g., ~/src/github.com/",
|
|
3559
|
+
newRepoName,
|
|
3560
|
+
"): "
|
|
3561
|
+
] }),
|
|
3562
|
+
/* @__PURE__ */ jsx14(
|
|
3563
|
+
TextInput3,
|
|
3564
|
+
{
|
|
3565
|
+
value: newRepoPath,
|
|
3566
|
+
onChange: setNewRepoPath,
|
|
3567
|
+
onSubmit: () => {
|
|
3568
|
+
if (newRepoPath) {
|
|
3569
|
+
setScreen("add-desc");
|
|
3570
|
+
}
|
|
3571
|
+
},
|
|
3572
|
+
placeholder: `~/src/github.com/${newRepoName}`
|
|
3573
|
+
}
|
|
3574
|
+
)
|
|
3575
|
+
] }),
|
|
3576
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: "esc back" }) })
|
|
3577
|
+
] });
|
|
3578
|
+
}
|
|
3579
|
+
if (screen === "add-desc") {
|
|
3580
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 2, children: [
|
|
3581
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.text, bold: true, children: "Add Repository" }),
|
|
3582
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
|
|
3583
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: "Name: " }),
|
|
3584
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.text, children: newRepoName })
|
|
3585
|
+
] }),
|
|
3586
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
|
|
3587
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: "Path: " }),
|
|
3588
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.text, children: newRepoPath })
|
|
3589
|
+
] }),
|
|
3590
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
|
|
3591
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: "Description (optional): " }),
|
|
3592
|
+
/* @__PURE__ */ jsx14(
|
|
3593
|
+
TextInput3,
|
|
3594
|
+
{
|
|
3595
|
+
value: newRepoDesc,
|
|
3596
|
+
onChange: setNewRepoDesc,
|
|
3597
|
+
onSubmit: handleAddRepo
|
|
3598
|
+
}
|
|
3599
|
+
)
|
|
3600
|
+
] }),
|
|
3601
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: "enter save \xB7 esc back" }) })
|
|
3602
|
+
] });
|
|
3603
|
+
}
|
|
3604
|
+
if (screen === "confirm-delete" && repoToDelete) {
|
|
3605
|
+
const repo = repos2.find((r) => r.name === repoToDelete);
|
|
3606
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 2, children: [
|
|
3607
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.text, bold: true, children: "Remove Repository" }),
|
|
3608
|
+
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
3609
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.text, children: repo?.name }),
|
|
3610
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: repo?.path })
|
|
3611
|
+
] }),
|
|
3612
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 2, children: /* @__PURE__ */ jsx14(Text14, { color: colors.error, children: "Remove this repository from the registry?" }) }),
|
|
3613
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: "y yes \xB7 n no" }) })
|
|
3614
|
+
] });
|
|
3615
|
+
}
|
|
3616
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", padding: 2, children: [
|
|
3617
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.text, bold: true, children: "Manage Repositories" }),
|
|
3618
|
+
message && /* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text14, { color: message.type === "success" ? colors.success : colors.error, children: message.text }) }),
|
|
3619
|
+
/* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", marginTop: 1, children: [
|
|
3620
|
+
repos2.length === 0 ? /* @__PURE__ */ jsx14(Box13, { marginY: 1, children: /* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: "No repos configured" }) }) : repos2.map((repo, index) => /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", marginTop: index > 0 ? 1 : 0, children: [
|
|
3621
|
+
/* @__PURE__ */ jsx14(Box13, { children: /* @__PURE__ */ jsxs13(
|
|
3622
|
+
Text14,
|
|
3623
|
+
{
|
|
3624
|
+
color: selectedIndex === index ? colors.primary : colors.text,
|
|
3625
|
+
bold: selectedIndex === index,
|
|
3626
|
+
children: [
|
|
3627
|
+
selectedIndex === index ? "> " : " ",
|
|
3628
|
+
repo.name
|
|
3629
|
+
]
|
|
3630
|
+
}
|
|
3631
|
+
) }),
|
|
3632
|
+
/* @__PURE__ */ jsx14(Box13, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: repo.path }) }),
|
|
3633
|
+
repo.description && /* @__PURE__ */ jsx14(Box13, { paddingLeft: 2, children: /* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: repo.description }) })
|
|
3634
|
+
] }, repo.name)),
|
|
3635
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: repos2.length > 0 ? 2 : 0, children: /* @__PURE__ */ jsxs13(
|
|
3636
|
+
Text14,
|
|
3637
|
+
{
|
|
3638
|
+
color: selectedIndex === repos2.length ? colors.primary : colors.textDim,
|
|
3639
|
+
bold: selectedIndex === repos2.length,
|
|
3640
|
+
children: [
|
|
3641
|
+
selectedIndex === repos2.length ? "> " : " ",
|
|
3642
|
+
"+ Add New Repository"
|
|
3643
|
+
]
|
|
3644
|
+
}
|
|
3645
|
+
) })
|
|
3646
|
+
] }),
|
|
3647
|
+
/* @__PURE__ */ jsx14(Box13, { marginTop: 2, children: /* @__PURE__ */ jsx14(Text14, { color: colors.textDim, children: repos2.length > 0 && selectedIndex < repos2.length ? "enter remove \xB7 esc back" : "\u2191\u2193 navigate \xB7 enter select \xB7 esc back" }) })
|
|
3648
|
+
] });
|
|
3649
|
+
}
|
|
3650
|
+
|
|
3651
|
+
// src/commands/tui/views/ReposViewerScreen.tsx
|
|
3652
|
+
import { Box as Box14, Text as Text15, useInput as useInput8 } from "ink";
|
|
3653
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3654
|
+
function ReposViewerScreen({ onClose }) {
|
|
3655
|
+
const repos2 = getRepos();
|
|
3656
|
+
useInput8((input, key) => {
|
|
3657
|
+
if (key.escape) {
|
|
3658
|
+
onClose();
|
|
3659
|
+
}
|
|
3660
|
+
});
|
|
3661
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", padding: 2, children: [
|
|
3662
|
+
/* @__PURE__ */ jsx15(Text15, { color: colors.text, bold: true, children: "Repositories" }),
|
|
3663
|
+
repos2.length === 0 ? /* @__PURE__ */ jsx15(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text15, { color: colors.textDim, children: "No repos configured" }) }) : /* @__PURE__ */ jsx15(Box14, { flexDirection: "column", marginTop: 1, children: repos2.map((repo, index) => /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", marginTop: index > 0 ? 2 : 0, children: [
|
|
3664
|
+
/* @__PURE__ */ jsx15(Text15, { color: colors.text, bold: true, children: repo.name }),
|
|
3665
|
+
/* @__PURE__ */ jsx15(Box14, { marginTop: 0, children: /* @__PURE__ */ jsxs14(Text15, { color: colors.textDim, children: [
|
|
3666
|
+
"Path: ",
|
|
3667
|
+
repo.path
|
|
3668
|
+
] }) }),
|
|
3669
|
+
repo.description && /* @__PURE__ */ jsx15(Box14, { marginTop: 0, children: /* @__PURE__ */ jsx15(Text15, { color: colors.textDim, children: repo.description }) })
|
|
3670
|
+
] }, repo.name)) }),
|
|
3671
|
+
/* @__PURE__ */ jsx15(Box14, { marginTop: 2, children: /* @__PURE__ */ jsx15(Text15, { color: colors.textDim, children: "esc back" }) })
|
|
3672
|
+
] });
|
|
3673
|
+
}
|
|
3674
|
+
|
|
3269
3675
|
// src/commands/tui/hooks/useAppUpdate.ts
|
|
3270
|
-
import { useState as
|
|
3676
|
+
import { useState as useState8, useMemo as useMemo5 } from "react";
|
|
3271
3677
|
import { useApp } from "ink";
|
|
3272
3678
|
function useAppUpdate({ onUpdateSuccess, onUpdateFailure }) {
|
|
3273
3679
|
const { exit } = useApp();
|
|
3274
|
-
const [isUpdating, setIsUpdating] =
|
|
3680
|
+
const [isUpdating, setIsUpdating] = useState8(false);
|
|
3275
3681
|
const updateInfo = useMemo5(() => getUpdateInfo(), []);
|
|
3276
3682
|
const handleUpdate = () => {
|
|
3277
3683
|
setIsUpdating(true);
|
|
@@ -3313,11 +3719,11 @@ ${dim}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u
|
|
|
3313
3719
|
}
|
|
3314
3720
|
|
|
3315
3721
|
// src/commands/tui/hooks/useToolUpdates.ts
|
|
3316
|
-
import { useState as
|
|
3722
|
+
import { useState as useState9, useCallback } from "react";
|
|
3317
3723
|
function useToolUpdates({ onUpdateComplete }) {
|
|
3318
|
-
const [toolUpdates, setToolUpdates] =
|
|
3319
|
-
const [isUpdatingTools, setIsUpdatingTools] =
|
|
3320
|
-
const [autoUpdatedTools, setAutoUpdatedTools] =
|
|
3724
|
+
const [toolUpdates, setToolUpdates] = useState9([]);
|
|
3725
|
+
const [isUpdatingTools, setIsUpdatingTools] = useState9(false);
|
|
3726
|
+
const [autoUpdatedTools, setAutoUpdatedTools] = useState9([]);
|
|
3321
3727
|
const tools = getBundledTools();
|
|
3322
3728
|
const ensureSystemTools = useCallback(() => {
|
|
3323
3729
|
const systemTools = tools.filter((t) => t.system === true);
|
|
@@ -3385,7 +3791,7 @@ function useToolUpdates({ onUpdateComplete }) {
|
|
|
3385
3791
|
}
|
|
3386
3792
|
|
|
3387
3793
|
// src/commands/tui.tsx
|
|
3388
|
-
import { Fragment as Fragment2, jsx as
|
|
3794
|
+
import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3389
3795
|
var exitMessage = null;
|
|
3390
3796
|
function App() {
|
|
3391
3797
|
const { exit } = useApp2();
|
|
@@ -3393,17 +3799,17 @@ function App() {
|
|
|
3393
3799
|
{ id: "tools", label: "Tools" },
|
|
3394
3800
|
{ id: "settings", label: "Settings" }
|
|
3395
3801
|
];
|
|
3396
|
-
const [activeTab, setActiveTab] =
|
|
3397
|
-
const [tabIndex, setTabIndex] =
|
|
3398
|
-
const [view, setView] =
|
|
3399
|
-
const [selectedIndex, setSelectedIndex] =
|
|
3400
|
-
const [selectedAction, setSelectedAction] =
|
|
3401
|
-
const [scrollOffset, setScrollOffset] =
|
|
3402
|
-
const [message, setMessage] =
|
|
3403
|
-
const [isEditingSettings, setIsEditingSettings] =
|
|
3404
|
-
const [readmeContent, setReadmeContent] =
|
|
3405
|
-
const [previousView, setPreviousView] =
|
|
3406
|
-
const [detectedPlatforms, setDetectedPlatforms] =
|
|
3802
|
+
const [activeTab, setActiveTab] = useState10("tools");
|
|
3803
|
+
const [tabIndex, setTabIndex] = useState10(0);
|
|
3804
|
+
const [view, setView] = useState10("welcome");
|
|
3805
|
+
const [selectedIndex, setSelectedIndex] = useState10(0);
|
|
3806
|
+
const [selectedAction, setSelectedAction] = useState10(0);
|
|
3807
|
+
const [scrollOffset, setScrollOffset] = useState10(0);
|
|
3808
|
+
const [message, setMessage] = useState10(null);
|
|
3809
|
+
const [isEditingSettings, setIsEditingSettings] = useState10(false);
|
|
3810
|
+
const [readmeContent, setReadmeContent] = useState10(null);
|
|
3811
|
+
const [previousView, setPreviousView] = useState10("detail");
|
|
3812
|
+
const [detectedPlatforms, setDetectedPlatforms] = useState10(() => detectAllPlatforms());
|
|
3407
3813
|
const handleRedetectPlatforms = () => {
|
|
3408
3814
|
setDetectedPlatforms(detectAllPlatforms());
|
|
3409
3815
|
};
|
|
@@ -3472,7 +3878,7 @@ function App() {
|
|
|
3472
3878
|
};
|
|
3473
3879
|
const tools = getBundledTools();
|
|
3474
3880
|
const skills = getBundledSkills();
|
|
3475
|
-
|
|
3881
|
+
useInput9(
|
|
3476
3882
|
(input, key) => {
|
|
3477
3883
|
if (message) setMessage(null);
|
|
3478
3884
|
if (input === "q") {
|
|
@@ -3528,9 +3934,21 @@ function App() {
|
|
|
3528
3934
|
setSelectedAction(0);
|
|
3529
3935
|
}
|
|
3530
3936
|
if (activeTab === "settings") {
|
|
3937
|
+
if (key.leftArrow) {
|
|
3938
|
+
setSelectedAction((prev) => Math.max(0, prev - 1));
|
|
3939
|
+
}
|
|
3940
|
+
if (key.rightArrow) {
|
|
3941
|
+
setSelectedAction((prev) => Math.min(2, prev + 1));
|
|
3942
|
+
}
|
|
3531
3943
|
if (key.return) {
|
|
3532
|
-
|
|
3533
|
-
|
|
3944
|
+
if (selectedAction === 0) {
|
|
3945
|
+
setIsEditingSettings(true);
|
|
3946
|
+
setView("setup");
|
|
3947
|
+
} else if (selectedAction === 1) {
|
|
3948
|
+
setView("view-repos");
|
|
3949
|
+
} else if (selectedAction === 2) {
|
|
3950
|
+
setView("repos");
|
|
3951
|
+
}
|
|
3534
3952
|
}
|
|
3535
3953
|
}
|
|
3536
3954
|
if (key.leftArrow && activeTab === "tools") {
|
|
@@ -3608,7 +4026,7 @@ function App() {
|
|
|
3608
4026
|
}
|
|
3609
4027
|
},
|
|
3610
4028
|
{
|
|
3611
|
-
isActive: view !== "welcome" && view !== "tool-updates" && view !== "setup" && view !== "configure" && view !== "explorer"
|
|
4029
|
+
isActive: view !== "welcome" && view !== "tool-updates" && view !== "setup" && view !== "configure" && view !== "explorer" && view !== "repos" && view !== "view-repos"
|
|
3612
4030
|
}
|
|
3613
4031
|
);
|
|
3614
4032
|
const selectedTool = activeTab === "tools" ? tools[selectedIndex] ?? null : null;
|
|
@@ -3616,7 +4034,7 @@ function App() {
|
|
|
3616
4034
|
(s) => s.name === (selectedTool.includes.skills.find((sk) => sk.required)?.name || selectedTool.name)
|
|
3617
4035
|
) : null;
|
|
3618
4036
|
if (view === "welcome") {
|
|
3619
|
-
return /* @__PURE__ */
|
|
4037
|
+
return /* @__PURE__ */ jsx16(
|
|
3620
4038
|
WelcomeScreen,
|
|
3621
4039
|
{
|
|
3622
4040
|
updateInfo,
|
|
@@ -3629,7 +4047,7 @@ function App() {
|
|
|
3629
4047
|
);
|
|
3630
4048
|
}
|
|
3631
4049
|
if (view === "tool-updates" && toolUpdates.length > 0) {
|
|
3632
|
-
return /* @__PURE__ */
|
|
4050
|
+
return /* @__PURE__ */ jsx16(
|
|
3633
4051
|
ToolUpdatePrompt,
|
|
3634
4052
|
{
|
|
3635
4053
|
toolUpdates,
|
|
@@ -3641,7 +4059,7 @@ function App() {
|
|
|
3641
4059
|
);
|
|
3642
4060
|
}
|
|
3643
4061
|
if (view === "setup") {
|
|
3644
|
-
return /* @__PURE__ */
|
|
4062
|
+
return /* @__PURE__ */ jsx16(
|
|
3645
4063
|
SetupScreen,
|
|
3646
4064
|
{
|
|
3647
4065
|
onComplete: () => {
|
|
@@ -3658,7 +4076,7 @@ function App() {
|
|
|
3658
4076
|
);
|
|
3659
4077
|
}
|
|
3660
4078
|
if (view === "readme" && readmeContent) {
|
|
3661
|
-
return /* @__PURE__ */
|
|
4079
|
+
return /* @__PURE__ */ jsx16(
|
|
3662
4080
|
ReadmeViewer,
|
|
3663
4081
|
{
|
|
3664
4082
|
title: readmeContent.title,
|
|
@@ -3671,7 +4089,7 @@ function App() {
|
|
|
3671
4089
|
);
|
|
3672
4090
|
}
|
|
3673
4091
|
if (view === "explorer" && selectedTool) {
|
|
3674
|
-
return /* @__PURE__ */
|
|
4092
|
+
return /* @__PURE__ */ jsx16(
|
|
3675
4093
|
ToolExplorer,
|
|
3676
4094
|
{
|
|
3677
4095
|
tool: selectedTool,
|
|
@@ -3687,7 +4105,7 @@ function App() {
|
|
|
3687
4105
|
);
|
|
3688
4106
|
}
|
|
3689
4107
|
if (view === "configure" && selectedSkillForConfig) {
|
|
3690
|
-
return /* @__PURE__ */
|
|
4108
|
+
return /* @__PURE__ */ jsx16(
|
|
3691
4109
|
SkillConfigScreen,
|
|
3692
4110
|
{
|
|
3693
4111
|
skill: selectedSkillForConfig,
|
|
@@ -3704,43 +4122,70 @@ function App() {
|
|
|
3704
4122
|
}
|
|
3705
4123
|
);
|
|
3706
4124
|
}
|
|
3707
|
-
|
|
3708
|
-
/* @__PURE__ */
|
|
3709
|
-
|
|
4125
|
+
if (view === "view-repos") {
|
|
4126
|
+
return /* @__PURE__ */ jsx16(
|
|
4127
|
+
ReposViewerScreen,
|
|
4128
|
+
{
|
|
4129
|
+
onClose: () => {
|
|
4130
|
+
setView("detail");
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4133
|
+
);
|
|
4134
|
+
}
|
|
4135
|
+
if (view === "repos") {
|
|
4136
|
+
return /* @__PURE__ */ jsx16(
|
|
4137
|
+
ReposManagementScreen,
|
|
4138
|
+
{
|
|
4139
|
+
onComplete: () => {
|
|
4140
|
+
setMessage({
|
|
4141
|
+
text: "\u2713 Repos updated",
|
|
4142
|
+
type: "success"
|
|
4143
|
+
});
|
|
4144
|
+
setView("detail");
|
|
4145
|
+
},
|
|
4146
|
+
onCancel: () => {
|
|
4147
|
+
setView("detail");
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
);
|
|
4151
|
+
}
|
|
4152
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "row", padding: 1, children: [
|
|
4153
|
+
/* @__PURE__ */ jsxs15(
|
|
4154
|
+
Box15,
|
|
3710
4155
|
{
|
|
3711
4156
|
flexDirection: "column",
|
|
3712
4157
|
width: 44,
|
|
3713
4158
|
borderStyle: "single",
|
|
3714
4159
|
borderColor: colors.border,
|
|
3715
4160
|
children: [
|
|
3716
|
-
/* @__PURE__ */
|
|
3717
|
-
/* @__PURE__ */
|
|
3718
|
-
/* @__PURE__ */
|
|
3719
|
-
/* @__PURE__ */
|
|
3720
|
-
/* @__PURE__ */
|
|
3721
|
-
/* @__PURE__ */
|
|
3722
|
-
/* @__PURE__ */
|
|
3723
|
-
/* @__PURE__ */
|
|
4161
|
+
/* @__PURE__ */ jsx16(Box15, { paddingX: 1, children: /* @__PURE__ */ jsxs15(Text16, { children: [
|
|
4162
|
+
/* @__PURE__ */ jsx16(Text16, { color: colors.textDim, children: "[" }),
|
|
4163
|
+
/* @__PURE__ */ jsx16(Text16, { color: colors.primary, children: "\u25CF" }),
|
|
4164
|
+
/* @__PURE__ */ jsx16(Text16, { color: colors.textDim, children: " " }),
|
|
4165
|
+
/* @__PURE__ */ jsx16(Text16, { color: colors.primary, children: "\u25CF" }),
|
|
4166
|
+
/* @__PURE__ */ jsx16(Text16, { color: colors.textDim, children: "] " }),
|
|
4167
|
+
/* @__PURE__ */ jsx16(Text16, { color: colors.textMuted, children: "droid" }),
|
|
4168
|
+
/* @__PURE__ */ jsxs15(Text16, { color: colors.textDim, children: [
|
|
3724
4169
|
" v",
|
|
3725
4170
|
getVersion()
|
|
3726
4171
|
] })
|
|
3727
4172
|
] }) }),
|
|
3728
|
-
/* @__PURE__ */
|
|
4173
|
+
/* @__PURE__ */ jsx16(Box15, { paddingX: 1, children: /* @__PURE__ */ jsx16(
|
|
3729
4174
|
PlatformBadges,
|
|
3730
4175
|
{
|
|
3731
4176
|
detected: detectedPlatforms,
|
|
3732
4177
|
ignored: loadConfig().ignored_platforms ?? []
|
|
3733
4178
|
}
|
|
3734
4179
|
) }),
|
|
3735
|
-
/* @__PURE__ */
|
|
3736
|
-
/* @__PURE__ */
|
|
3737
|
-
activeTab === "tools" && /* @__PURE__ */
|
|
3738
|
-
scrollOffset > 0 && /* @__PURE__ */
|
|
4180
|
+
/* @__PURE__ */ jsx16(Box15, { paddingX: 1, marginTop: 1, children: /* @__PURE__ */ jsx16(TabBar, { tabs, activeTab }) }),
|
|
4181
|
+
/* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", marginTop: 1, children: [
|
|
4182
|
+
activeTab === "tools" && /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
4183
|
+
scrollOffset > 0 && /* @__PURE__ */ jsx16(Box15, { paddingX: 1, children: /* @__PURE__ */ jsxs15(Text16, { color: colors.textDim, children: [
|
|
3739
4184
|
"\u2191 ",
|
|
3740
4185
|
scrollOffset,
|
|
3741
4186
|
" more"
|
|
3742
4187
|
] }) }),
|
|
3743
|
-
tools.slice(scrollOffset, scrollOffset + MAX_VISIBLE_ITEMS).map((tool, index) => /* @__PURE__ */
|
|
4188
|
+
tools.slice(scrollOffset, scrollOffset + MAX_VISIBLE_ITEMS).map((tool, index) => /* @__PURE__ */ jsx16(
|
|
3744
4189
|
ToolItem,
|
|
3745
4190
|
{
|
|
3746
4191
|
tool,
|
|
@@ -3750,30 +4195,30 @@ function App() {
|
|
|
3750
4195
|
},
|
|
3751
4196
|
tool.name
|
|
3752
4197
|
)),
|
|
3753
|
-
scrollOffset + MAX_VISIBLE_ITEMS < tools.length && /* @__PURE__ */
|
|
4198
|
+
scrollOffset + MAX_VISIBLE_ITEMS < tools.length && /* @__PURE__ */ jsx16(Box15, { paddingX: 1, children: /* @__PURE__ */ jsxs15(Text16, { color: colors.textDim, children: [
|
|
3754
4199
|
"\u2193 ",
|
|
3755
4200
|
tools.length - scrollOffset - MAX_VISIBLE_ITEMS,
|
|
3756
4201
|
" more"
|
|
3757
4202
|
] }) }),
|
|
3758
|
-
tools.length > MAX_VISIBLE_ITEMS && /* @__PURE__ */
|
|
4203
|
+
tools.length > MAX_VISIBLE_ITEMS && /* @__PURE__ */ jsx16(Box15, { paddingX: 1, marginTop: 1, children: /* @__PURE__ */ jsxs15(Text16, { color: colors.textDim, children: [
|
|
3759
4204
|
tools.length,
|
|
3760
4205
|
" tools total"
|
|
3761
4206
|
] }) })
|
|
3762
4207
|
] }),
|
|
3763
|
-
activeTab === "settings" && /* @__PURE__ */
|
|
4208
|
+
activeTab === "settings" && /* @__PURE__ */ jsx16(Box15, { paddingX: 1, children: /* @__PURE__ */ jsx16(Text16, { color: colors.textDim, children: "View and edit config" }) })
|
|
3764
4209
|
] }),
|
|
3765
|
-
message && /* @__PURE__ */
|
|
3766
|
-
|
|
4210
|
+
message && /* @__PURE__ */ jsx16(Box15, { paddingX: 1, marginTop: 1, children: /* @__PURE__ */ jsx16(
|
|
4211
|
+
Text16,
|
|
3767
4212
|
{
|
|
3768
4213
|
color: message.type === "success" ? colors.success : colors.error,
|
|
3769
4214
|
children: message.text
|
|
3770
4215
|
}
|
|
3771
4216
|
) }),
|
|
3772
|
-
/* @__PURE__ */
|
|
4217
|
+
/* @__PURE__ */ jsx16(Box15, { paddingX: 1, marginTop: 1, children: /* @__PURE__ */ jsx16(Text16, { color: colors.textDim, children: view === "menu" ? "\u2190\u2192 \u2191\u2193 enter q" : "\u2190\u2192 enter esc q" }) })
|
|
3773
4218
|
]
|
|
3774
4219
|
}
|
|
3775
4220
|
),
|
|
3776
|
-
activeTab === "tools" && /* @__PURE__ */
|
|
4221
|
+
activeTab === "tools" && /* @__PURE__ */ jsx16(
|
|
3777
4222
|
ToolDetails,
|
|
3778
4223
|
{
|
|
3779
4224
|
tool: selectedTool,
|
|
@@ -3781,10 +4226,11 @@ function App() {
|
|
|
3781
4226
|
selectedAction
|
|
3782
4227
|
}
|
|
3783
4228
|
),
|
|
3784
|
-
activeTab === "settings" && /* @__PURE__ */
|
|
4229
|
+
activeTab === "settings" && /* @__PURE__ */ jsx16(
|
|
3785
4230
|
SettingsDetails,
|
|
3786
4231
|
{
|
|
3787
4232
|
isFocused: view === "detail",
|
|
4233
|
+
selectedAction,
|
|
3788
4234
|
detectedPlatforms,
|
|
3789
4235
|
onRedetect: detectedPlatforms.length === 0 ? handleRedetectPlatforms : void 0
|
|
3790
4236
|
}
|
|
@@ -3794,7 +4240,7 @@ function App() {
|
|
|
3794
4240
|
async function tuiCommand() {
|
|
3795
4241
|
process.stdout.write("\x1B[?1049h");
|
|
3796
4242
|
process.stdout.write("\x1B[H");
|
|
3797
|
-
const { waitUntilExit } = render(/* @__PURE__ */
|
|
4243
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx16(App, {}));
|
|
3798
4244
|
await waitUntilExit();
|
|
3799
4245
|
process.stdout.write("\x1B[?1049l");
|
|
3800
4246
|
if (exitMessage) {
|
|
@@ -3863,11 +4309,152 @@ async function execCommand(tool, script, args) {
|
|
|
3863
4309
|
});
|
|
3864
4310
|
}
|
|
3865
4311
|
|
|
4312
|
+
// src/commands/repos.ts
|
|
4313
|
+
import chalk10 from "chalk";
|
|
4314
|
+
import inquirer4 from "inquirer";
|
|
4315
|
+
async function reposListCommand(options) {
|
|
4316
|
+
const repos2 = getRepos();
|
|
4317
|
+
if (repos2.length === 0) {
|
|
4318
|
+
console.log(chalk10.yellow("No repos configured."));
|
|
4319
|
+
console.log(chalk10.gray("\nAdd a repo with:"));
|
|
4320
|
+
console.log(chalk10.gray(" droid repos add <name>"));
|
|
4321
|
+
return;
|
|
4322
|
+
}
|
|
4323
|
+
if (options?.json) {
|
|
4324
|
+
console.log(JSON.stringify(repos2, null, 2));
|
|
4325
|
+
return;
|
|
4326
|
+
}
|
|
4327
|
+
console.log(chalk10.bold("\n\u{1F4E6} Registered Repos\n"));
|
|
4328
|
+
for (const repo of repos2) {
|
|
4329
|
+
const expandedPath = getRepoPath(repo.name);
|
|
4330
|
+
console.log(chalk10.cyan(`${repo.name}`));
|
|
4331
|
+
console.log(chalk10.gray(` Path: ${expandedPath}`));
|
|
4332
|
+
if (repo.description) {
|
|
4333
|
+
console.log(chalk10.gray(` ${repo.description}`));
|
|
4334
|
+
}
|
|
4335
|
+
console.log();
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4338
|
+
async function reposAddCommand(name, path, description) {
|
|
4339
|
+
let repoName = name;
|
|
4340
|
+
let repoPath = path;
|
|
4341
|
+
let repoDescription = description;
|
|
4342
|
+
if (!repoName) {
|
|
4343
|
+
const answers = await inquirer4.prompt([
|
|
4344
|
+
{
|
|
4345
|
+
type: "input",
|
|
4346
|
+
name: "name",
|
|
4347
|
+
message: "Repo name:",
|
|
4348
|
+
validate: (input) => input.trim() ? true : "Name is required"
|
|
4349
|
+
}
|
|
4350
|
+
]);
|
|
4351
|
+
repoName = answers.name;
|
|
4352
|
+
}
|
|
4353
|
+
if (!repoPath) {
|
|
4354
|
+
const answers = await inquirer4.prompt([
|
|
4355
|
+
{
|
|
4356
|
+
type: "input",
|
|
4357
|
+
name: "path",
|
|
4358
|
+
message: "Repo path:",
|
|
4359
|
+
default: `~/src/github.com/${repoName}`,
|
|
4360
|
+
validate: (input) => input.trim() ? true : "Path is required"
|
|
4361
|
+
}
|
|
4362
|
+
]);
|
|
4363
|
+
repoPath = answers.path;
|
|
4364
|
+
}
|
|
4365
|
+
if (!repoDescription) {
|
|
4366
|
+
const answers = await inquirer4.prompt([
|
|
4367
|
+
{
|
|
4368
|
+
type: "input",
|
|
4369
|
+
name: "description",
|
|
4370
|
+
message: "Description (optional):"
|
|
4371
|
+
}
|
|
4372
|
+
]);
|
|
4373
|
+
repoDescription = answers.description || void 0;
|
|
4374
|
+
}
|
|
4375
|
+
if (!repoName || !repoPath) {
|
|
4376
|
+
console.error(chalk10.red("Name and path are required"));
|
|
4377
|
+
return;
|
|
4378
|
+
}
|
|
4379
|
+
const repo = {
|
|
4380
|
+
name: repoName,
|
|
4381
|
+
path: repoPath,
|
|
4382
|
+
description: repoDescription
|
|
4383
|
+
};
|
|
4384
|
+
addRepo(repo);
|
|
4385
|
+
const expandedPath = getRepoPath(repoName);
|
|
4386
|
+
console.log(chalk10.green(`
|
|
4387
|
+
\u2713 Added repo: ${repoName}`));
|
|
4388
|
+
console.log(chalk10.gray(` Path: ${expandedPath}`));
|
|
4389
|
+
if (repoDescription) {
|
|
4390
|
+
console.log(chalk10.gray(` ${repoDescription}`));
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
async function reposRemoveCommand(name) {
|
|
4394
|
+
let repoName = name;
|
|
4395
|
+
if (!repoName) {
|
|
4396
|
+
const repos2 = getRepos();
|
|
4397
|
+
if (repos2.length === 0) {
|
|
4398
|
+
console.log(chalk10.yellow("No repos configured."));
|
|
4399
|
+
return;
|
|
4400
|
+
}
|
|
4401
|
+
const answers2 = await inquirer4.prompt([
|
|
4402
|
+
{
|
|
4403
|
+
type: "list",
|
|
4404
|
+
name: "name",
|
|
4405
|
+
message: "Select repo to remove:",
|
|
4406
|
+
choices: repos2.map((r) => r.name)
|
|
4407
|
+
}
|
|
4408
|
+
]);
|
|
4409
|
+
repoName = answers2.name;
|
|
4410
|
+
}
|
|
4411
|
+
if (!repoName) {
|
|
4412
|
+
console.error(chalk10.red("Repo name is required"));
|
|
4413
|
+
return;
|
|
4414
|
+
}
|
|
4415
|
+
const answers = await inquirer4.prompt([
|
|
4416
|
+
{
|
|
4417
|
+
type: "confirm",
|
|
4418
|
+
name: "confirm",
|
|
4419
|
+
message: `Remove repo '${repoName}'?`,
|
|
4420
|
+
default: false
|
|
4421
|
+
}
|
|
4422
|
+
]);
|
|
4423
|
+
if (!answers.confirm) {
|
|
4424
|
+
console.log(chalk10.gray("Cancelled"));
|
|
4425
|
+
return;
|
|
4426
|
+
}
|
|
4427
|
+
const existed = removeRepo(repoName);
|
|
4428
|
+
if (existed) {
|
|
4429
|
+
console.log(chalk10.green(`
|
|
4430
|
+
\u2713 Removed repo: ${repoName}`));
|
|
4431
|
+
} else {
|
|
4432
|
+
console.log(chalk10.yellow(`
|
|
4433
|
+
Repo '${repoName}' not found`));
|
|
4434
|
+
}
|
|
4435
|
+
}
|
|
4436
|
+
async function reposGetCommand(name) {
|
|
4437
|
+
const repo = getRepo(name);
|
|
4438
|
+
if (!repo) {
|
|
4439
|
+
console.error(chalk10.red(`Repo '${name}' not found`));
|
|
4440
|
+
process.exit(1);
|
|
4441
|
+
}
|
|
4442
|
+
console.log(JSON.stringify(repo, null, 2));
|
|
4443
|
+
}
|
|
4444
|
+
|
|
3866
4445
|
// src/bin/droid.ts
|
|
3867
4446
|
var version = getVersion();
|
|
3868
4447
|
program.name("droid").description("Droid, teaching your AI new tricks").version(version);
|
|
3869
4448
|
program.command("setup").description("Interactive wizard for global configuration").action(setupCommand);
|
|
3870
4449
|
program.command("config").description("View or edit configuration").argument("[tool]", "Get merged config for a tool (for deterministic scripts)").option("-e, --edit", "Open config in editor").option("-g, --get <key>", "Get a specific config value").option("-s, --set <key=value>", "Set a config value").action(configCommand);
|
|
4450
|
+
var repos = program.command("repos").description("Manage repository registry");
|
|
4451
|
+
repos.command("list").description("List all registered repos").option("--json", "Output as JSON").action((options) => reposListCommand(options));
|
|
4452
|
+
repos.command("add [name]").description("Add a repo to the registry").option("-p, --path <path>", "Repository path").option("-d, --description <desc>", "Repository description").action(
|
|
4453
|
+
(name, options) => reposAddCommand(name, options.path, options.description)
|
|
4454
|
+
);
|
|
4455
|
+
repos.command("remove [name]").description("Remove a repo from the registry").action((name) => reposRemoveCommand(name));
|
|
4456
|
+
repos.command("get <name>").description("Get a specific repo (JSON output for scripts)").action((name) => reposGetCommand(name));
|
|
4457
|
+
repos.action(() => reposListCommand());
|
|
3871
4458
|
program.command("tools").description("Browse and manage available tools").action(skillsCommand);
|
|
3872
4459
|
program.command("install <tool>").description("Install a tool and run its setup wizard").action(installCommand);
|
|
3873
4460
|
program.command("uninstall <tool>").description("Uninstall a tool").action(uninstallCommand);
|