prjct-cli 1.6.10 → 1.6.12
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 +66 -1
- package/bin/prjct.ts +11 -2
- package/core/agentic/prompt-builder.ts +2 -2
- package/core/context-tools/imports-tool.ts +12 -9
- package/core/infrastructure/ai-provider.ts +17 -5
- package/core/infrastructure/command-installer.ts +10 -15
- package/core/infrastructure/setup.ts +9 -14
- package/core/utils/provider-cache.ts +49 -0
- package/core/utils/version.ts +3 -0
- package/dist/bin/prjct.mjs +1108 -1059
- package/dist/core/infrastructure/command-installer.js +140 -100
- package/dist/core/infrastructure/setup.js +260 -225
- package/package.json +1 -1
|
@@ -49,6 +49,42 @@ var init_fs_helpers = __esm({
|
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
+
// core/utils/provider-cache.ts
|
|
53
|
+
async function readProviderCache() {
|
|
54
|
+
try {
|
|
55
|
+
const raw = await import_promises2.default.readFile(CACHE_FILE, "utf-8");
|
|
56
|
+
const cache = JSON.parse(raw);
|
|
57
|
+
if (!cache.timestamp || !cache.detection) return null;
|
|
58
|
+
const age = Date.now() - new Date(cache.timestamp).getTime();
|
|
59
|
+
if (age > TTL_MS) return null;
|
|
60
|
+
return cache.detection;
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function writeProviderCache(detection) {
|
|
66
|
+
const cache = {
|
|
67
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
68
|
+
detection
|
|
69
|
+
};
|
|
70
|
+
await import_promises2.default.mkdir(CACHE_DIR, { recursive: true });
|
|
71
|
+
await import_promises2.default.writeFile(CACHE_FILE, JSON.stringify(cache, null, 2));
|
|
72
|
+
}
|
|
73
|
+
var import_promises2, import_node_os, import_node_path2, CACHE_DIR, CACHE_FILE, TTL_MS;
|
|
74
|
+
var init_provider_cache = __esm({
|
|
75
|
+
"core/utils/provider-cache.ts"() {
|
|
76
|
+
"use strict";
|
|
77
|
+
import_promises2 = __toESM(require("node:fs/promises"));
|
|
78
|
+
import_node_os = __toESM(require("node:os"));
|
|
79
|
+
import_node_path2 = __toESM(require("node:path"));
|
|
80
|
+
CACHE_DIR = import_node_path2.default.join(import_node_os.default.homedir(), ".prjct-cli", "cache");
|
|
81
|
+
CACHE_FILE = import_node_path2.default.join(CACHE_DIR, "providers.json");
|
|
82
|
+
TTL_MS = 10 * 60 * 1e3;
|
|
83
|
+
__name(readProviderCache, "readProviderCache");
|
|
84
|
+
__name(writeProviderCache, "writeProviderCache");
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
52
88
|
// core/infrastructure/ai-provider.ts
|
|
53
89
|
var ai_provider_exports = {};
|
|
54
90
|
__export(ai_provider_exports, {
|
|
@@ -77,7 +113,7 @@ __export(ai_provider_exports, {
|
|
|
77
113
|
});
|
|
78
114
|
async function whichCommand(command) {
|
|
79
115
|
try {
|
|
80
|
-
const { stdout } = await execAsync(`which ${command}
|
|
116
|
+
const { stdout } = await execAsync(`which ${command}`, { timeout: SPAWN_TIMEOUT_MS });
|
|
81
117
|
return stdout.trim();
|
|
82
118
|
} catch {
|
|
83
119
|
return null;
|
|
@@ -85,7 +121,7 @@ async function whichCommand(command) {
|
|
|
85
121
|
}
|
|
86
122
|
async function getCliVersion(command) {
|
|
87
123
|
try {
|
|
88
|
-
const { stdout } = await execAsync(`${command} --version
|
|
124
|
+
const { stdout } = await execAsync(`${command} --version`, { timeout: SPAWN_TIMEOUT_MS });
|
|
89
125
|
const match = stdout.match(/\d+\.\d+\.\d+/);
|
|
90
126
|
return match ? match[0] : stdout.trim();
|
|
91
127
|
} catch {
|
|
@@ -108,9 +144,16 @@ async function detectProvider(provider) {
|
|
|
108
144
|
path: cliPath
|
|
109
145
|
};
|
|
110
146
|
}
|
|
111
|
-
async function detectAllProviders() {
|
|
147
|
+
async function detectAllProviders(refresh = false) {
|
|
148
|
+
if (!refresh) {
|
|
149
|
+
const cached = await readProviderCache();
|
|
150
|
+
if (cached) return cached;
|
|
151
|
+
}
|
|
112
152
|
const [claude, gemini] = await Promise.all([detectProvider("claude"), detectProvider("gemini")]);
|
|
113
|
-
|
|
153
|
+
const detection = { claude, gemini };
|
|
154
|
+
await writeProviderCache(detection).catch(() => {
|
|
155
|
+
});
|
|
156
|
+
return detection;
|
|
114
157
|
}
|
|
115
158
|
async function getActiveProvider(projectProvider) {
|
|
116
159
|
if (projectProvider && Providers[projectProvider]) {
|
|
@@ -147,9 +190,9 @@ function getProviderBranding(provider) {
|
|
|
147
190
|
};
|
|
148
191
|
}
|
|
149
192
|
async function detectCursorProject(projectRoot) {
|
|
150
|
-
const cursorDir =
|
|
151
|
-
const rulesDir =
|
|
152
|
-
const routerPath =
|
|
193
|
+
const cursorDir = import_node_path3.default.join(projectRoot, ".cursor");
|
|
194
|
+
const rulesDir = import_node_path3.default.join(cursorDir, "rules");
|
|
195
|
+
const routerPath = import_node_path3.default.join(rulesDir, "prjct.mdc");
|
|
153
196
|
const [detected, routerInstalled] = await Promise.all([
|
|
154
197
|
fileExists(cursorDir),
|
|
155
198
|
fileExists(routerPath)
|
|
@@ -165,9 +208,9 @@ async function needsCursorRouterRegeneration(projectRoot) {
|
|
|
165
208
|
return detection.detected && !detection.routerInstalled;
|
|
166
209
|
}
|
|
167
210
|
async function detectWindsurfProject(projectRoot) {
|
|
168
|
-
const windsurfDir =
|
|
169
|
-
const rulesDir =
|
|
170
|
-
const routerPath =
|
|
211
|
+
const windsurfDir = import_node_path3.default.join(projectRoot, ".windsurf");
|
|
212
|
+
const rulesDir = import_node_path3.default.join(windsurfDir, "rules");
|
|
213
|
+
const routerPath = import_node_path3.default.join(rulesDir, "prjct.md");
|
|
171
214
|
const [detected, routerInstalled] = await Promise.all([
|
|
172
215
|
fileExists(windsurfDir),
|
|
173
216
|
fileExists(routerPath)
|
|
@@ -187,7 +230,7 @@ async function detectAntigravity() {
|
|
|
187
230
|
if (!configPath) {
|
|
188
231
|
return { installed: false, skillInstalled: false };
|
|
189
232
|
}
|
|
190
|
-
const skillPath =
|
|
233
|
+
const skillPath = import_node_path3.default.join(configPath, "skills", "prjct", "SKILL.md");
|
|
191
234
|
const [installed, skillInstalled] = await Promise.all([
|
|
192
235
|
fileExists(configPath),
|
|
193
236
|
fileExists(skillPath)
|
|
@@ -203,14 +246,14 @@ function getGlobalContextPath(provider) {
|
|
|
203
246
|
if (!config.configDir) {
|
|
204
247
|
return null;
|
|
205
248
|
}
|
|
206
|
-
return
|
|
249
|
+
return import_node_path3.default.join(config.configDir, config.contextFile);
|
|
207
250
|
}
|
|
208
251
|
function getGlobalSettingsPath(provider) {
|
|
209
252
|
const config = Providers[provider];
|
|
210
253
|
if (!config.configDir || !config.settingsFile) {
|
|
211
254
|
return null;
|
|
212
255
|
}
|
|
213
|
-
return
|
|
256
|
+
return import_node_path3.default.join(config.configDir, config.settingsFile);
|
|
214
257
|
}
|
|
215
258
|
function getSkillsPath(provider) {
|
|
216
259
|
return Providers[provider].skillsDir;
|
|
@@ -220,7 +263,7 @@ function getCommandsDir(provider) {
|
|
|
220
263
|
}
|
|
221
264
|
function getProjectCommandsPath(provider, projectRoot) {
|
|
222
265
|
const config = Providers[provider];
|
|
223
|
-
return
|
|
266
|
+
return import_node_path3.default.join(projectRoot, config.commandsDir);
|
|
224
267
|
}
|
|
225
268
|
async function selectProvider() {
|
|
226
269
|
const detection = await detectAllProviders();
|
|
@@ -254,23 +297,25 @@ async function selectProvider() {
|
|
|
254
297
|
detection
|
|
255
298
|
};
|
|
256
299
|
}
|
|
257
|
-
var import_node_child_process,
|
|
300
|
+
var import_node_child_process, import_node_os2, import_node_path3, import_node_util, execAsync, SPAWN_TIMEOUT_MS, ClaudeProvider, GeminiProvider, AntigravityProvider, CursorProvider, WindsurfProvider, Providers;
|
|
258
301
|
var init_ai_provider = __esm({
|
|
259
302
|
"core/infrastructure/ai-provider.ts"() {
|
|
260
303
|
"use strict";
|
|
261
304
|
import_node_child_process = require("node:child_process");
|
|
262
|
-
|
|
263
|
-
|
|
305
|
+
import_node_os2 = __toESM(require("node:os"));
|
|
306
|
+
import_node_path3 = __toESM(require("node:path"));
|
|
264
307
|
import_node_util = require("node:util");
|
|
265
308
|
init_fs_helpers();
|
|
309
|
+
init_provider_cache();
|
|
266
310
|
execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
|
|
311
|
+
SPAWN_TIMEOUT_MS = 2e3;
|
|
267
312
|
ClaudeProvider = {
|
|
268
313
|
name: "claude",
|
|
269
314
|
displayName: "Claude Code",
|
|
270
315
|
cliCommand: "claude",
|
|
271
|
-
configDir:
|
|
316
|
+
configDir: import_node_path3.default.join(import_node_os2.default.homedir(), ".claude"),
|
|
272
317
|
contextFile: "CLAUDE.md",
|
|
273
|
-
skillsDir:
|
|
318
|
+
skillsDir: import_node_path3.default.join(import_node_os2.default.homedir(), ".claude", "skills"),
|
|
274
319
|
commandsDir: ".claude/commands",
|
|
275
320
|
commandFormat: "md",
|
|
276
321
|
settingsFile: "settings.json",
|
|
@@ -283,9 +328,9 @@ var init_ai_provider = __esm({
|
|
|
283
328
|
name: "gemini",
|
|
284
329
|
displayName: "Gemini CLI",
|
|
285
330
|
cliCommand: "gemini",
|
|
286
|
-
configDir:
|
|
331
|
+
configDir: import_node_path3.default.join(import_node_os2.default.homedir(), ".gemini"),
|
|
287
332
|
contextFile: "GEMINI.md",
|
|
288
|
-
skillsDir:
|
|
333
|
+
skillsDir: import_node_path3.default.join(import_node_os2.default.homedir(), ".gemini", "skills"),
|
|
289
334
|
commandsDir: ".gemini/commands",
|
|
290
335
|
commandFormat: "toml",
|
|
291
336
|
settingsFile: "settings.json",
|
|
@@ -299,9 +344,9 @@ var init_ai_provider = __esm({
|
|
|
299
344
|
displayName: "Google Antigravity",
|
|
300
345
|
cliCommand: null,
|
|
301
346
|
// Not a CLI command, but a platform/app
|
|
302
|
-
configDir:
|
|
347
|
+
configDir: import_node_path3.default.join(import_node_os2.default.homedir(), ".gemini", "antigravity"),
|
|
303
348
|
contextFile: "ANTIGRAVITY.md",
|
|
304
|
-
skillsDir:
|
|
349
|
+
skillsDir: import_node_path3.default.join(import_node_os2.default.homedir(), ".gemini", "antigravity", "global_skills"),
|
|
305
350
|
commandsDir: ".agent/skills",
|
|
306
351
|
// Antigravity uses .agent/skills in projects
|
|
307
352
|
commandFormat: "md",
|
|
@@ -401,9 +446,9 @@ __export(command_installer_exports, {
|
|
|
401
446
|
isRouterInstalled: () => isRouterInstalled
|
|
402
447
|
});
|
|
403
448
|
module.exports = __toCommonJS(command_installer_exports);
|
|
404
|
-
var
|
|
405
|
-
var
|
|
406
|
-
var
|
|
449
|
+
var import_promises3 = __toESM(require("node:fs/promises"));
|
|
450
|
+
var import_node_os3 = __toESM(require("node:os"));
|
|
451
|
+
var import_node_path4 = __toESM(require("node:path"));
|
|
407
452
|
|
|
408
453
|
// core/types/fs.ts
|
|
409
454
|
function isNodeError(error) {
|
|
@@ -472,8 +517,8 @@ var PACKAGE_ROOT = getPackageRoot();
|
|
|
472
517
|
// core/infrastructure/command-installer.ts
|
|
473
518
|
async function loadModuleConfig() {
|
|
474
519
|
try {
|
|
475
|
-
const configPath =
|
|
476
|
-
const content = await
|
|
520
|
+
const configPath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/modules/module-config.json");
|
|
521
|
+
const content = await import_promises3.default.readFile(configPath, "utf-8");
|
|
477
522
|
return JSON.parse(content);
|
|
478
523
|
} catch {
|
|
479
524
|
return null;
|
|
@@ -482,18 +527,18 @@ async function loadModuleConfig() {
|
|
|
482
527
|
__name(loadModuleConfig, "loadModuleConfig");
|
|
483
528
|
async function composeGlobalTemplate(profile) {
|
|
484
529
|
const config = await loadModuleConfig();
|
|
485
|
-
const modulesDir =
|
|
530
|
+
const modulesDir = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/modules");
|
|
486
531
|
if (!config) {
|
|
487
|
-
const legacyPath =
|
|
488
|
-
return
|
|
532
|
+
const legacyPath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
|
|
533
|
+
return import_promises3.default.readFile(legacyPath, "utf-8");
|
|
489
534
|
}
|
|
490
535
|
const profileName = profile || config.default;
|
|
491
536
|
const selectedProfile = config.profiles[profileName];
|
|
492
537
|
if (!selectedProfile) {
|
|
493
538
|
const defaultProfile = config.profiles[config.default];
|
|
494
539
|
if (!defaultProfile) {
|
|
495
|
-
const legacyPath =
|
|
496
|
-
return
|
|
540
|
+
const legacyPath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
|
|
541
|
+
return import_promises3.default.readFile(legacyPath, "utf-8");
|
|
497
542
|
}
|
|
498
543
|
}
|
|
499
544
|
const modules = (selectedProfile || config.profiles[config.default]).modules;
|
|
@@ -501,8 +546,8 @@ async function composeGlobalTemplate(profile) {
|
|
|
501
546
|
parts.push("<!-- prjct:start - DO NOT REMOVE THIS MARKER -->");
|
|
502
547
|
for (const moduleName of modules) {
|
|
503
548
|
try {
|
|
504
|
-
const modulePath =
|
|
505
|
-
const content = await
|
|
549
|
+
const modulePath = import_node_path4.default.join(modulesDir, moduleName);
|
|
550
|
+
const content = await import_promises3.default.readFile(modulePath, "utf-8");
|
|
506
551
|
parts.push("");
|
|
507
552
|
parts.push(content);
|
|
508
553
|
} catch {
|
|
@@ -523,16 +568,16 @@ async function getProfileForCommand(command) {
|
|
|
523
568
|
__name(getProfileForCommand, "getProfileForCommand");
|
|
524
569
|
async function installDocs() {
|
|
525
570
|
try {
|
|
526
|
-
const docsDir =
|
|
527
|
-
const templateDocsDir =
|
|
528
|
-
await
|
|
529
|
-
const docFiles = await
|
|
571
|
+
const docsDir = import_node_path4.default.join(import_node_os3.default.homedir(), ".prjct-cli", "docs");
|
|
572
|
+
const templateDocsDir = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/docs");
|
|
573
|
+
await import_promises3.default.mkdir(docsDir, { recursive: true });
|
|
574
|
+
const docFiles = await import_promises3.default.readdir(templateDocsDir);
|
|
530
575
|
for (const file of docFiles) {
|
|
531
576
|
if (file.endsWith(".md")) {
|
|
532
|
-
const srcPath =
|
|
533
|
-
const destPath =
|
|
534
|
-
const content = await
|
|
535
|
-
await
|
|
577
|
+
const srcPath = import_node_path4.default.join(templateDocsDir, file);
|
|
578
|
+
const destPath = import_node_path4.default.join(docsDir, file);
|
|
579
|
+
const content = await import_promises3.default.readFile(srcPath, "utf-8");
|
|
580
|
+
await import_promises3.default.writeFile(destPath, content, "utf-8");
|
|
536
581
|
}
|
|
537
582
|
}
|
|
538
583
|
return { success: true };
|
|
@@ -554,28 +599,23 @@ async function installGlobalConfig() {
|
|
|
554
599
|
};
|
|
555
600
|
}
|
|
556
601
|
try {
|
|
557
|
-
await
|
|
558
|
-
const globalConfigPath =
|
|
559
|
-
const templatePath =
|
|
560
|
-
getPackageRoot(),
|
|
561
|
-
"templates",
|
|
562
|
-
"global",
|
|
563
|
-
activeProvider.contextFile
|
|
564
|
-
);
|
|
602
|
+
await import_promises3.default.mkdir(activeProvider.configDir, { recursive: true });
|
|
603
|
+
const globalConfigPath = import_node_path4.default.join(activeProvider.configDir, activeProvider.contextFile);
|
|
604
|
+
const templatePath = import_node_path4.default.join(PACKAGE_ROOT, "templates", "global", activeProvider.contextFile);
|
|
565
605
|
let templateContent = "";
|
|
566
606
|
try {
|
|
567
|
-
templateContent = await
|
|
607
|
+
templateContent = await import_promises3.default.readFile(templatePath, "utf-8");
|
|
568
608
|
} catch (_error) {
|
|
569
609
|
if (providerName === "claude") {
|
|
570
610
|
try {
|
|
571
611
|
templateContent = await composeGlobalTemplate("standard");
|
|
572
612
|
} catch {
|
|
573
|
-
const fallbackTemplatePath =
|
|
574
|
-
templateContent = await
|
|
613
|
+
const fallbackTemplatePath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
|
|
614
|
+
templateContent = await import_promises3.default.readFile(fallbackTemplatePath, "utf-8");
|
|
575
615
|
}
|
|
576
616
|
} else {
|
|
577
|
-
const fallbackTemplatePath =
|
|
578
|
-
templateContent = await
|
|
617
|
+
const fallbackTemplatePath = import_node_path4.default.join(PACKAGE_ROOT, "templates/global/CLAUDE.md");
|
|
618
|
+
templateContent = await import_promises3.default.readFile(fallbackTemplatePath, "utf-8");
|
|
579
619
|
if (providerName === "gemini") {
|
|
580
620
|
templateContent = templateContent.replace(/Claude/g, "Gemini");
|
|
581
621
|
}
|
|
@@ -584,7 +624,7 @@ async function installGlobalConfig() {
|
|
|
584
624
|
let existingContent = "";
|
|
585
625
|
let fileExists2 = false;
|
|
586
626
|
try {
|
|
587
|
-
existingContent = await
|
|
627
|
+
existingContent = await import_promises3.default.readFile(globalConfigPath, "utf-8");
|
|
588
628
|
fileExists2 = true;
|
|
589
629
|
} catch (error) {
|
|
590
630
|
if (isNotFoundError(error)) {
|
|
@@ -594,7 +634,7 @@ async function installGlobalConfig() {
|
|
|
594
634
|
}
|
|
595
635
|
}
|
|
596
636
|
if (!fileExists2) {
|
|
597
|
-
await
|
|
637
|
+
await import_promises3.default.writeFile(globalConfigPath, templateContent, "utf-8");
|
|
598
638
|
return {
|
|
599
639
|
success: true,
|
|
600
640
|
action: "created",
|
|
@@ -608,7 +648,7 @@ async function installGlobalConfig() {
|
|
|
608
648
|
const updatedContent = `${existingContent}
|
|
609
649
|
|
|
610
650
|
${templateContent}`;
|
|
611
|
-
await
|
|
651
|
+
await import_promises3.default.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
612
652
|
return {
|
|
613
653
|
success: true,
|
|
614
654
|
action: "appended",
|
|
@@ -624,7 +664,7 @@ ${templateContent}`;
|
|
|
624
664
|
templateContent.indexOf(endMarker) + endMarker.length
|
|
625
665
|
);
|
|
626
666
|
const updatedContent = beforeMarker + prjctSection + afterMarker;
|
|
627
|
-
await
|
|
667
|
+
await import_promises3.default.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
628
668
|
return {
|
|
629
669
|
success: true,
|
|
630
670
|
action: "updated",
|
|
@@ -651,17 +691,17 @@ var CommandInstaller = class {
|
|
|
651
691
|
templatesDir;
|
|
652
692
|
_initialized = false;
|
|
653
693
|
constructor() {
|
|
654
|
-
this.homeDir =
|
|
655
|
-
this.templatesDir =
|
|
694
|
+
this.homeDir = import_node_os3.default.homedir();
|
|
695
|
+
this.templatesDir = import_node_path4.default.join(PACKAGE_ROOT, "templates", "commands");
|
|
656
696
|
}
|
|
657
697
|
async ensureInit() {
|
|
658
698
|
if (this._initialized) return;
|
|
659
699
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
660
700
|
const activeProvider = await aiProvider.getActiveProvider();
|
|
661
701
|
if (activeProvider.name === "gemini") {
|
|
662
|
-
this.claudeCommandsPath =
|
|
702
|
+
this.claudeCommandsPath = import_node_path4.default.join(activeProvider.configDir, "commands");
|
|
663
703
|
} else {
|
|
664
|
-
this.claudeCommandsPath =
|
|
704
|
+
this.claudeCommandsPath = import_node_path4.default.join(activeProvider.configDir, "commands", "p");
|
|
665
705
|
}
|
|
666
706
|
this.claudeConfigPath = activeProvider.configDir;
|
|
667
707
|
this._initialized = true;
|
|
@@ -672,7 +712,7 @@ var CommandInstaller = class {
|
|
|
672
712
|
async detectActiveProvider() {
|
|
673
713
|
await this.ensureInit();
|
|
674
714
|
try {
|
|
675
|
-
await
|
|
715
|
+
await import_promises3.default.access(this.claudeConfigPath);
|
|
676
716
|
return true;
|
|
677
717
|
} catch (error) {
|
|
678
718
|
if (isNotFoundError(error)) {
|
|
@@ -692,7 +732,7 @@ var CommandInstaller = class {
|
|
|
692
732
|
*/
|
|
693
733
|
async getCommandFiles() {
|
|
694
734
|
try {
|
|
695
|
-
const files = await
|
|
735
|
+
const files = await import_promises3.default.readdir(this.templatesDir);
|
|
696
736
|
return files.filter((f) => f.endsWith(".md"));
|
|
697
737
|
} catch (_error) {
|
|
698
738
|
return [
|
|
@@ -733,16 +773,16 @@ var CommandInstaller = class {
|
|
|
733
773
|
}
|
|
734
774
|
try {
|
|
735
775
|
await this.installRouter();
|
|
736
|
-
await
|
|
776
|
+
await import_promises3.default.mkdir(this.claudeCommandsPath, { recursive: true });
|
|
737
777
|
const commandFiles = await this.getCommandFiles();
|
|
738
778
|
const installed = [];
|
|
739
779
|
const errors = [];
|
|
740
780
|
for (const file of commandFiles) {
|
|
741
781
|
try {
|
|
742
|
-
const sourcePath =
|
|
743
|
-
const destPath =
|
|
744
|
-
const content = await
|
|
745
|
-
await
|
|
782
|
+
const sourcePath = import_node_path4.default.join(this.templatesDir, file);
|
|
783
|
+
const destPath = import_node_path4.default.join(this.claudeCommandsPath, file);
|
|
784
|
+
const content = await import_promises3.default.readFile(sourcePath, "utf-8");
|
|
785
|
+
await import_promises3.default.writeFile(destPath, content, "utf-8");
|
|
746
786
|
installed.push(file.replace(".md", ""));
|
|
747
787
|
} catch (error) {
|
|
748
788
|
errors.push({ file, error: getErrorMessage(error) });
|
|
@@ -771,8 +811,8 @@ var CommandInstaller = class {
|
|
|
771
811
|
const errors = [];
|
|
772
812
|
for (const file of commandFiles) {
|
|
773
813
|
try {
|
|
774
|
-
const filePath =
|
|
775
|
-
await
|
|
814
|
+
const filePath = import_node_path4.default.join(this.claudeCommandsPath, file);
|
|
815
|
+
await import_promises3.default.unlink(filePath);
|
|
776
816
|
uninstalled.push(file.replace(".md", ""));
|
|
777
817
|
} catch (error) {
|
|
778
818
|
if (error.code !== "ENOENT") {
|
|
@@ -781,7 +821,7 @@ var CommandInstaller = class {
|
|
|
781
821
|
}
|
|
782
822
|
}
|
|
783
823
|
try {
|
|
784
|
-
await
|
|
824
|
+
await import_promises3.default.rmdir(this.claudeCommandsPath);
|
|
785
825
|
} catch (_error) {
|
|
786
826
|
}
|
|
787
827
|
return {
|
|
@@ -808,8 +848,8 @@ var CommandInstaller = class {
|
|
|
808
848
|
};
|
|
809
849
|
}
|
|
810
850
|
try {
|
|
811
|
-
await
|
|
812
|
-
const files = await
|
|
851
|
+
await import_promises3.default.access(this.claudeCommandsPath);
|
|
852
|
+
const files = await import_promises3.default.readdir(this.claudeCommandsPath);
|
|
813
853
|
const installedCommands = files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
|
|
814
854
|
return {
|
|
815
855
|
installed: installedCommands.length > 0,
|
|
@@ -857,8 +897,8 @@ var CommandInstaller = class {
|
|
|
857
897
|
*/
|
|
858
898
|
async verifyTemplate(commandName) {
|
|
859
899
|
try {
|
|
860
|
-
const templatePath =
|
|
861
|
-
await
|
|
900
|
+
const templatePath = import_node_path4.default.join(this.templatesDir, `${commandName}.md`);
|
|
901
|
+
await import_promises3.default.access(templatePath);
|
|
862
902
|
return true;
|
|
863
903
|
} catch (error) {
|
|
864
904
|
if (isNotFoundError(error)) {
|
|
@@ -876,11 +916,11 @@ var CommandInstaller = class {
|
|
|
876
916
|
const activeProvider = await aiProvider.getActiveProvider();
|
|
877
917
|
const routerFile = activeProvider.name === "gemini" ? "p.toml" : "p.md";
|
|
878
918
|
try {
|
|
879
|
-
const routerSource =
|
|
880
|
-
const routerDest =
|
|
881
|
-
await
|
|
882
|
-
const content = await
|
|
883
|
-
await
|
|
919
|
+
const routerSource = import_node_path4.default.join(this.templatesDir, routerFile);
|
|
920
|
+
const routerDest = import_node_path4.default.join(activeProvider.configDir, "commands", routerFile);
|
|
921
|
+
await import_promises3.default.mkdir(import_node_path4.default.dirname(routerDest), { recursive: true });
|
|
922
|
+
const content = await import_promises3.default.readFile(routerSource, "utf-8");
|
|
923
|
+
await import_promises3.default.writeFile(routerDest, content, "utf-8");
|
|
884
924
|
return true;
|
|
885
925
|
} catch (error) {
|
|
886
926
|
if (isNotFoundError(error)) {
|
|
@@ -896,14 +936,14 @@ var CommandInstaller = class {
|
|
|
896
936
|
async removeLegacyCommands() {
|
|
897
937
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
898
938
|
const activeProvider = await aiProvider.getActiveProvider();
|
|
899
|
-
const commandsRoot =
|
|
939
|
+
const commandsRoot = import_node_path4.default.join(activeProvider.configDir, "commands");
|
|
900
940
|
let removed = 0;
|
|
901
941
|
try {
|
|
902
|
-
const files = await
|
|
942
|
+
const files = await import_promises3.default.readdir(commandsRoot);
|
|
903
943
|
const legacyFiles = files.filter((f) => f.startsWith("p.") && f.endsWith(".md"));
|
|
904
944
|
for (const file of legacyFiles) {
|
|
905
945
|
try {
|
|
906
|
-
await
|
|
946
|
+
await import_promises3.default.unlink(import_node_path4.default.join(commandsRoot, file));
|
|
907
947
|
removed++;
|
|
908
948
|
} catch {
|
|
909
949
|
}
|
|
@@ -928,11 +968,11 @@ var CommandInstaller = class {
|
|
|
928
968
|
}
|
|
929
969
|
try {
|
|
930
970
|
await this.installRouter();
|
|
931
|
-
await
|
|
971
|
+
await import_promises3.default.mkdir(this.claudeCommandsPath, { recursive: true });
|
|
932
972
|
const templateFiles = await this.getCommandFiles();
|
|
933
973
|
let installedFiles = [];
|
|
934
974
|
try {
|
|
935
|
-
installedFiles = await
|
|
975
|
+
installedFiles = await import_promises3.default.readdir(this.claudeCommandsPath);
|
|
936
976
|
installedFiles = installedFiles.filter((f) => f.endsWith(".md"));
|
|
937
977
|
} catch (error) {
|
|
938
978
|
if (isNotFoundError(error)) {
|
|
@@ -950,11 +990,11 @@ var CommandInstaller = class {
|
|
|
950
990
|
};
|
|
951
991
|
for (const file of templateFiles) {
|
|
952
992
|
try {
|
|
953
|
-
const sourcePath =
|
|
954
|
-
const destPath =
|
|
993
|
+
const sourcePath = import_node_path4.default.join(this.templatesDir, file);
|
|
994
|
+
const destPath = import_node_path4.default.join(this.claudeCommandsPath, file);
|
|
955
995
|
const exists = installedFiles.includes(file);
|
|
956
|
-
const content = await
|
|
957
|
-
await
|
|
996
|
+
const content = await import_promises3.default.readFile(sourcePath, "utf-8");
|
|
997
|
+
await import_promises3.default.writeFile(destPath, content, "utf-8");
|
|
958
998
|
if (!exists) {
|
|
959
999
|
results.added++;
|
|
960
1000
|
} else {
|
|
@@ -990,17 +1030,17 @@ var CommandInstaller = class {
|
|
|
990
1030
|
}
|
|
991
1031
|
};
|
|
992
1032
|
function getProviderPaths() {
|
|
993
|
-
const homeDir =
|
|
1033
|
+
const homeDir = import_node_os3.default.homedir();
|
|
994
1034
|
return {
|
|
995
1035
|
claude: {
|
|
996
|
-
commands:
|
|
997
|
-
config:
|
|
998
|
-
router:
|
|
1036
|
+
commands: import_node_path4.default.join(homeDir, ".claude", "commands", "p"),
|
|
1037
|
+
config: import_node_path4.default.join(homeDir, ".claude"),
|
|
1038
|
+
router: import_node_path4.default.join(homeDir, ".claude", "commands", "p.md")
|
|
999
1039
|
},
|
|
1000
1040
|
gemini: {
|
|
1001
|
-
commands:
|
|
1002
|
-
config:
|
|
1003
|
-
router:
|
|
1041
|
+
commands: import_node_path4.default.join(homeDir, ".gemini", "commands"),
|
|
1042
|
+
config: import_node_path4.default.join(homeDir, ".gemini"),
|
|
1043
|
+
router: import_node_path4.default.join(homeDir, ".gemini", "commands", "p.toml")
|
|
1004
1044
|
}
|
|
1005
1045
|
};
|
|
1006
1046
|
}
|
|
@@ -1009,7 +1049,7 @@ async function isRouterInstalled(provider) {
|
|
|
1009
1049
|
const paths = getProviderPaths();
|
|
1010
1050
|
const routerPath = paths[provider].router;
|
|
1011
1051
|
try {
|
|
1012
|
-
await
|
|
1052
|
+
await import_promises3.default.access(routerPath);
|
|
1013
1053
|
return true;
|
|
1014
1054
|
} catch {
|
|
1015
1055
|
return false;
|