prjct-cli 1.6.9 → 1.6.11
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/bus/bus.ts +24 -0
- package/core/infrastructure/ai-provider.ts +17 -5
- package/core/services/watch-service.ts +20 -3
- package/core/utils/provider-cache.ts +49 -0
- package/dist/bin/prjct.mjs +1120 -1046
- package/dist/core/infrastructure/command-installer.js +140 -95
- package/dist/core/infrastructure/setup.js +260 -215
- 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(getPackageRoot(), "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(getPackageRoot(), "templates/global/modules");
|
|
486
531
|
if (!config) {
|
|
487
|
-
const legacyPath =
|
|
488
|
-
return
|
|
532
|
+
const legacyPath = import_node_path4.default.join(getPackageRoot(), "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(getPackageRoot(), "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(getPackageRoot(), "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,9 +599,9 @@ async function installGlobalConfig() {
|
|
|
554
599
|
};
|
|
555
600
|
}
|
|
556
601
|
try {
|
|
557
|
-
await
|
|
558
|
-
const globalConfigPath =
|
|
559
|
-
const templatePath =
|
|
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(
|
|
560
605
|
getPackageRoot(),
|
|
561
606
|
"templates",
|
|
562
607
|
"global",
|
|
@@ -564,18 +609,18 @@ async function installGlobalConfig() {
|
|
|
564
609
|
);
|
|
565
610
|
let templateContent = "";
|
|
566
611
|
try {
|
|
567
|
-
templateContent = await
|
|
612
|
+
templateContent = await import_promises3.default.readFile(templatePath, "utf-8");
|
|
568
613
|
} catch (_error) {
|
|
569
614
|
if (providerName === "claude") {
|
|
570
615
|
try {
|
|
571
616
|
templateContent = await composeGlobalTemplate("standard");
|
|
572
617
|
} catch {
|
|
573
|
-
const fallbackTemplatePath =
|
|
574
|
-
templateContent = await
|
|
618
|
+
const fallbackTemplatePath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
|
|
619
|
+
templateContent = await import_promises3.default.readFile(fallbackTemplatePath, "utf-8");
|
|
575
620
|
}
|
|
576
621
|
} else {
|
|
577
|
-
const fallbackTemplatePath =
|
|
578
|
-
templateContent = await
|
|
622
|
+
const fallbackTemplatePath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
|
|
623
|
+
templateContent = await import_promises3.default.readFile(fallbackTemplatePath, "utf-8");
|
|
579
624
|
if (providerName === "gemini") {
|
|
580
625
|
templateContent = templateContent.replace(/Claude/g, "Gemini");
|
|
581
626
|
}
|
|
@@ -584,7 +629,7 @@ async function installGlobalConfig() {
|
|
|
584
629
|
let existingContent = "";
|
|
585
630
|
let fileExists2 = false;
|
|
586
631
|
try {
|
|
587
|
-
existingContent = await
|
|
632
|
+
existingContent = await import_promises3.default.readFile(globalConfigPath, "utf-8");
|
|
588
633
|
fileExists2 = true;
|
|
589
634
|
} catch (error) {
|
|
590
635
|
if (isNotFoundError(error)) {
|
|
@@ -594,7 +639,7 @@ async function installGlobalConfig() {
|
|
|
594
639
|
}
|
|
595
640
|
}
|
|
596
641
|
if (!fileExists2) {
|
|
597
|
-
await
|
|
642
|
+
await import_promises3.default.writeFile(globalConfigPath, templateContent, "utf-8");
|
|
598
643
|
return {
|
|
599
644
|
success: true,
|
|
600
645
|
action: "created",
|
|
@@ -608,7 +653,7 @@ async function installGlobalConfig() {
|
|
|
608
653
|
const updatedContent = `${existingContent}
|
|
609
654
|
|
|
610
655
|
${templateContent}`;
|
|
611
|
-
await
|
|
656
|
+
await import_promises3.default.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
612
657
|
return {
|
|
613
658
|
success: true,
|
|
614
659
|
action: "appended",
|
|
@@ -624,7 +669,7 @@ ${templateContent}`;
|
|
|
624
669
|
templateContent.indexOf(endMarker) + endMarker.length
|
|
625
670
|
);
|
|
626
671
|
const updatedContent = beforeMarker + prjctSection + afterMarker;
|
|
627
|
-
await
|
|
672
|
+
await import_promises3.default.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
628
673
|
return {
|
|
629
674
|
success: true,
|
|
630
675
|
action: "updated",
|
|
@@ -651,17 +696,17 @@ var CommandInstaller = class {
|
|
|
651
696
|
templatesDir;
|
|
652
697
|
_initialized = false;
|
|
653
698
|
constructor() {
|
|
654
|
-
this.homeDir =
|
|
655
|
-
this.templatesDir =
|
|
699
|
+
this.homeDir = import_node_os3.default.homedir();
|
|
700
|
+
this.templatesDir = import_node_path4.default.join(getPackageRoot(), "templates", "commands");
|
|
656
701
|
}
|
|
657
702
|
async ensureInit() {
|
|
658
703
|
if (this._initialized) return;
|
|
659
704
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
660
705
|
const activeProvider = await aiProvider.getActiveProvider();
|
|
661
706
|
if (activeProvider.name === "gemini") {
|
|
662
|
-
this.claudeCommandsPath =
|
|
707
|
+
this.claudeCommandsPath = import_node_path4.default.join(activeProvider.configDir, "commands");
|
|
663
708
|
} else {
|
|
664
|
-
this.claudeCommandsPath =
|
|
709
|
+
this.claudeCommandsPath = import_node_path4.default.join(activeProvider.configDir, "commands", "p");
|
|
665
710
|
}
|
|
666
711
|
this.claudeConfigPath = activeProvider.configDir;
|
|
667
712
|
this._initialized = true;
|
|
@@ -672,7 +717,7 @@ var CommandInstaller = class {
|
|
|
672
717
|
async detectActiveProvider() {
|
|
673
718
|
await this.ensureInit();
|
|
674
719
|
try {
|
|
675
|
-
await
|
|
720
|
+
await import_promises3.default.access(this.claudeConfigPath);
|
|
676
721
|
return true;
|
|
677
722
|
} catch (error) {
|
|
678
723
|
if (isNotFoundError(error)) {
|
|
@@ -692,7 +737,7 @@ var CommandInstaller = class {
|
|
|
692
737
|
*/
|
|
693
738
|
async getCommandFiles() {
|
|
694
739
|
try {
|
|
695
|
-
const files = await
|
|
740
|
+
const files = await import_promises3.default.readdir(this.templatesDir);
|
|
696
741
|
return files.filter((f) => f.endsWith(".md"));
|
|
697
742
|
} catch (_error) {
|
|
698
743
|
return [
|
|
@@ -733,16 +778,16 @@ var CommandInstaller = class {
|
|
|
733
778
|
}
|
|
734
779
|
try {
|
|
735
780
|
await this.installRouter();
|
|
736
|
-
await
|
|
781
|
+
await import_promises3.default.mkdir(this.claudeCommandsPath, { recursive: true });
|
|
737
782
|
const commandFiles = await this.getCommandFiles();
|
|
738
783
|
const installed = [];
|
|
739
784
|
const errors = [];
|
|
740
785
|
for (const file of commandFiles) {
|
|
741
786
|
try {
|
|
742
|
-
const sourcePath =
|
|
743
|
-
const destPath =
|
|
744
|
-
const content = await
|
|
745
|
-
await
|
|
787
|
+
const sourcePath = import_node_path4.default.join(this.templatesDir, file);
|
|
788
|
+
const destPath = import_node_path4.default.join(this.claudeCommandsPath, file);
|
|
789
|
+
const content = await import_promises3.default.readFile(sourcePath, "utf-8");
|
|
790
|
+
await import_promises3.default.writeFile(destPath, content, "utf-8");
|
|
746
791
|
installed.push(file.replace(".md", ""));
|
|
747
792
|
} catch (error) {
|
|
748
793
|
errors.push({ file, error: getErrorMessage(error) });
|
|
@@ -771,8 +816,8 @@ var CommandInstaller = class {
|
|
|
771
816
|
const errors = [];
|
|
772
817
|
for (const file of commandFiles) {
|
|
773
818
|
try {
|
|
774
|
-
const filePath =
|
|
775
|
-
await
|
|
819
|
+
const filePath = import_node_path4.default.join(this.claudeCommandsPath, file);
|
|
820
|
+
await import_promises3.default.unlink(filePath);
|
|
776
821
|
uninstalled.push(file.replace(".md", ""));
|
|
777
822
|
} catch (error) {
|
|
778
823
|
if (error.code !== "ENOENT") {
|
|
@@ -781,7 +826,7 @@ var CommandInstaller = class {
|
|
|
781
826
|
}
|
|
782
827
|
}
|
|
783
828
|
try {
|
|
784
|
-
await
|
|
829
|
+
await import_promises3.default.rmdir(this.claudeCommandsPath);
|
|
785
830
|
} catch (_error) {
|
|
786
831
|
}
|
|
787
832
|
return {
|
|
@@ -808,8 +853,8 @@ var CommandInstaller = class {
|
|
|
808
853
|
};
|
|
809
854
|
}
|
|
810
855
|
try {
|
|
811
|
-
await
|
|
812
|
-
const files = await
|
|
856
|
+
await import_promises3.default.access(this.claudeCommandsPath);
|
|
857
|
+
const files = await import_promises3.default.readdir(this.claudeCommandsPath);
|
|
813
858
|
const installedCommands = files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
|
|
814
859
|
return {
|
|
815
860
|
installed: installedCommands.length > 0,
|
|
@@ -857,8 +902,8 @@ var CommandInstaller = class {
|
|
|
857
902
|
*/
|
|
858
903
|
async verifyTemplate(commandName) {
|
|
859
904
|
try {
|
|
860
|
-
const templatePath =
|
|
861
|
-
await
|
|
905
|
+
const templatePath = import_node_path4.default.join(this.templatesDir, `${commandName}.md`);
|
|
906
|
+
await import_promises3.default.access(templatePath);
|
|
862
907
|
return true;
|
|
863
908
|
} catch (error) {
|
|
864
909
|
if (isNotFoundError(error)) {
|
|
@@ -876,11 +921,11 @@ var CommandInstaller = class {
|
|
|
876
921
|
const activeProvider = await aiProvider.getActiveProvider();
|
|
877
922
|
const routerFile = activeProvider.name === "gemini" ? "p.toml" : "p.md";
|
|
878
923
|
try {
|
|
879
|
-
const routerSource =
|
|
880
|
-
const routerDest =
|
|
881
|
-
await
|
|
882
|
-
const content = await
|
|
883
|
-
await
|
|
924
|
+
const routerSource = import_node_path4.default.join(this.templatesDir, routerFile);
|
|
925
|
+
const routerDest = import_node_path4.default.join(activeProvider.configDir, "commands", routerFile);
|
|
926
|
+
await import_promises3.default.mkdir(import_node_path4.default.dirname(routerDest), { recursive: true });
|
|
927
|
+
const content = await import_promises3.default.readFile(routerSource, "utf-8");
|
|
928
|
+
await import_promises3.default.writeFile(routerDest, content, "utf-8");
|
|
884
929
|
return true;
|
|
885
930
|
} catch (error) {
|
|
886
931
|
if (isNotFoundError(error)) {
|
|
@@ -896,14 +941,14 @@ var CommandInstaller = class {
|
|
|
896
941
|
async removeLegacyCommands() {
|
|
897
942
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
898
943
|
const activeProvider = await aiProvider.getActiveProvider();
|
|
899
|
-
const commandsRoot =
|
|
944
|
+
const commandsRoot = import_node_path4.default.join(activeProvider.configDir, "commands");
|
|
900
945
|
let removed = 0;
|
|
901
946
|
try {
|
|
902
|
-
const files = await
|
|
947
|
+
const files = await import_promises3.default.readdir(commandsRoot);
|
|
903
948
|
const legacyFiles = files.filter((f) => f.startsWith("p.") && f.endsWith(".md"));
|
|
904
949
|
for (const file of legacyFiles) {
|
|
905
950
|
try {
|
|
906
|
-
await
|
|
951
|
+
await import_promises3.default.unlink(import_node_path4.default.join(commandsRoot, file));
|
|
907
952
|
removed++;
|
|
908
953
|
} catch {
|
|
909
954
|
}
|
|
@@ -928,11 +973,11 @@ var CommandInstaller = class {
|
|
|
928
973
|
}
|
|
929
974
|
try {
|
|
930
975
|
await this.installRouter();
|
|
931
|
-
await
|
|
976
|
+
await import_promises3.default.mkdir(this.claudeCommandsPath, { recursive: true });
|
|
932
977
|
const templateFiles = await this.getCommandFiles();
|
|
933
978
|
let installedFiles = [];
|
|
934
979
|
try {
|
|
935
|
-
installedFiles = await
|
|
980
|
+
installedFiles = await import_promises3.default.readdir(this.claudeCommandsPath);
|
|
936
981
|
installedFiles = installedFiles.filter((f) => f.endsWith(".md"));
|
|
937
982
|
} catch (error) {
|
|
938
983
|
if (isNotFoundError(error)) {
|
|
@@ -950,11 +995,11 @@ var CommandInstaller = class {
|
|
|
950
995
|
};
|
|
951
996
|
for (const file of templateFiles) {
|
|
952
997
|
try {
|
|
953
|
-
const sourcePath =
|
|
954
|
-
const destPath =
|
|
998
|
+
const sourcePath = import_node_path4.default.join(this.templatesDir, file);
|
|
999
|
+
const destPath = import_node_path4.default.join(this.claudeCommandsPath, file);
|
|
955
1000
|
const exists = installedFiles.includes(file);
|
|
956
|
-
const content = await
|
|
957
|
-
await
|
|
1001
|
+
const content = await import_promises3.default.readFile(sourcePath, "utf-8");
|
|
1002
|
+
await import_promises3.default.writeFile(destPath, content, "utf-8");
|
|
958
1003
|
if (!exists) {
|
|
959
1004
|
results.added++;
|
|
960
1005
|
} else {
|
|
@@ -990,17 +1035,17 @@ var CommandInstaller = class {
|
|
|
990
1035
|
}
|
|
991
1036
|
};
|
|
992
1037
|
function getProviderPaths() {
|
|
993
|
-
const homeDir =
|
|
1038
|
+
const homeDir = import_node_os3.default.homedir();
|
|
994
1039
|
return {
|
|
995
1040
|
claude: {
|
|
996
|
-
commands:
|
|
997
|
-
config:
|
|
998
|
-
router:
|
|
1041
|
+
commands: import_node_path4.default.join(homeDir, ".claude", "commands", "p"),
|
|
1042
|
+
config: import_node_path4.default.join(homeDir, ".claude"),
|
|
1043
|
+
router: import_node_path4.default.join(homeDir, ".claude", "commands", "p.md")
|
|
999
1044
|
},
|
|
1000
1045
|
gemini: {
|
|
1001
|
-
commands:
|
|
1002
|
-
config:
|
|
1003
|
-
router:
|
|
1046
|
+
commands: import_node_path4.default.join(homeDir, ".gemini", "commands"),
|
|
1047
|
+
config: import_node_path4.default.join(homeDir, ".gemini"),
|
|
1048
|
+
router: import_node_path4.default.join(homeDir, ".gemini", "commands", "p.toml")
|
|
1004
1049
|
}
|
|
1005
1050
|
};
|
|
1006
1051
|
}
|
|
@@ -1009,7 +1054,7 @@ async function isRouterInstalled(provider) {
|
|
|
1009
1054
|
const paths = getProviderPaths();
|
|
1010
1055
|
const routerPath = paths[provider].router;
|
|
1011
1056
|
try {
|
|
1012
|
-
await
|
|
1057
|
+
await import_promises3.default.access(routerPath);
|
|
1013
1058
|
return true;
|
|
1014
1059
|
} catch {
|
|
1015
1060
|
return false;
|