prjct-cli 1.5.0 → 1.6.0
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 +117 -1
- package/bin/prjct.ts +23 -14
- package/core/__tests__/agentic/command-executor.test.ts +19 -19
- package/core/__tests__/agentic/prompt-builder.test.ts +16 -16
- package/core/__tests__/utils/output.test.ts +7 -1
- package/core/agentic/command-executor.ts +18 -17
- package/core/agentic/orchestrator-executor.ts +126 -8
- package/core/agentic/prompt-builder.ts +58 -20
- package/core/agentic/template-executor.ts +2 -2
- package/core/ai-tools/registry.ts +18 -15
- package/core/cli/start.ts +18 -17
- package/core/commands/analysis.ts +6 -1
- package/core/commands/setup.ts +8 -8
- package/core/commands/uninstall.ts +11 -11
- package/core/context-tools/token-counter.ts +2 -0
- package/core/domain/agent-loader.ts +35 -1
- package/core/index.ts +12 -11
- package/core/infrastructure/agent-detector.ts +8 -8
- package/core/infrastructure/ai-provider.ts +49 -37
- package/core/infrastructure/command-installer.ts +18 -10
- package/core/infrastructure/path-manager.ts +4 -4
- package/core/infrastructure/setup.ts +124 -119
- package/core/infrastructure/update-checker.ts +14 -13
- package/core/integrations/linear/sync.ts +4 -4
- package/core/services/context-selector.ts +6 -3
- package/core/services/hierarchical-agent-resolver.ts +2 -0
- package/core/services/hooks-service.ts +78 -68
- package/core/services/sync-service.ts +115 -3
- package/core/session/compaction.ts +1 -1
- package/core/types/agentic.ts +22 -0
- package/core/types/agents.ts +5 -0
- package/core/types/index.ts +1 -0
- package/core/utils/fs-helpers.ts +14 -0
- package/core/utils/output.ts +15 -1
- package/core/utils/project-credentials.ts +8 -7
- package/dist/bin/prjct.mjs +1446 -750
- package/dist/core/infrastructure/command-installer.js +118 -87
- package/dist/core/infrastructure/setup.js +246 -210
- package/package.json +1 -1
- package/templates/config/skill-mappings.json +23 -60
- package/templates/subagents/domain/backend.md +1 -0
- package/templates/subagents/domain/database.md +1 -0
- package/templates/subagents/domain/devops.md +1 -0
- package/templates/subagents/domain/frontend.md +1 -0
- package/templates/subagents/domain/testing.md +1 -0
- package/templates/subagents/workflow/chief-architect.md +2 -1
- package/templates/subagents/workflow/prjct-planner.md +2 -1
- package/templates/subagents/workflow/prjct-shipper.md +1 -0
- package/templates/subagents/workflow/prjct-workflow.md +1 -0
|
@@ -31,6 +31,24 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
));
|
|
32
32
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
33
|
|
|
34
|
+
// core/utils/fs-helpers.ts
|
|
35
|
+
async function fileExists(filePath) {
|
|
36
|
+
try {
|
|
37
|
+
await import_promises.default.access(filePath);
|
|
38
|
+
return true;
|
|
39
|
+
} catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
var import_promises;
|
|
44
|
+
var init_fs_helpers = __esm({
|
|
45
|
+
"core/utils/fs-helpers.ts"() {
|
|
46
|
+
"use strict";
|
|
47
|
+
import_promises = __toESM(require("node:fs/promises"));
|
|
48
|
+
__name(fileExists, "fileExists");
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
34
52
|
// core/infrastructure/ai-provider.ts
|
|
35
53
|
var ai_provider_exports = {};
|
|
36
54
|
__export(ai_provider_exports, {
|
|
@@ -58,50 +76,48 @@ __export(ai_provider_exports, {
|
|
|
58
76
|
needsWindsurfRouterRegeneration: () => needsWindsurfRouterRegeneration,
|
|
59
77
|
selectProvider: () => selectProvider
|
|
60
78
|
});
|
|
61
|
-
function whichCommand(command) {
|
|
79
|
+
async function whichCommand(command) {
|
|
62
80
|
try {
|
|
63
|
-
const
|
|
64
|
-
return
|
|
81
|
+
const { stdout } = await execAsync(`which ${command}`);
|
|
82
|
+
return stdout.trim();
|
|
65
83
|
} catch {
|
|
66
84
|
return null;
|
|
67
85
|
}
|
|
68
86
|
}
|
|
69
|
-
function getCliVersion(command) {
|
|
87
|
+
async function getCliVersion(command) {
|
|
70
88
|
try {
|
|
71
|
-
const
|
|
72
|
-
const match =
|
|
73
|
-
return match ? match[0] :
|
|
89
|
+
const { stdout } = await execAsync(`${command} --version`);
|
|
90
|
+
const match = stdout.match(/\d+\.\d+\.\d+/);
|
|
91
|
+
return match ? match[0] : stdout.trim();
|
|
74
92
|
} catch {
|
|
75
93
|
return null;
|
|
76
94
|
}
|
|
77
95
|
}
|
|
78
|
-
function detectProvider(provider) {
|
|
96
|
+
async function detectProvider(provider) {
|
|
79
97
|
const config = Providers[provider];
|
|
80
98
|
if (!config.cliCommand) {
|
|
81
99
|
return { installed: false };
|
|
82
100
|
}
|
|
83
|
-
const cliPath = whichCommand(config.cliCommand);
|
|
101
|
+
const cliPath = await whichCommand(config.cliCommand);
|
|
84
102
|
if (!cliPath) {
|
|
85
103
|
return { installed: false };
|
|
86
104
|
}
|
|
87
|
-
const version = getCliVersion(config.cliCommand);
|
|
105
|
+
const version = await getCliVersion(config.cliCommand);
|
|
88
106
|
return {
|
|
89
107
|
installed: true,
|
|
90
108
|
version: version || void 0,
|
|
91
109
|
path: cliPath
|
|
92
110
|
};
|
|
93
111
|
}
|
|
94
|
-
function detectAllProviders() {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
gemini: detectProvider("gemini")
|
|
98
|
-
};
|
|
112
|
+
async function detectAllProviders() {
|
|
113
|
+
const [claude, gemini] = await Promise.all([detectProvider("claude"), detectProvider("gemini")]);
|
|
114
|
+
return { claude, gemini };
|
|
99
115
|
}
|
|
100
|
-
function getActiveProvider(projectProvider) {
|
|
116
|
+
async function getActiveProvider(projectProvider) {
|
|
101
117
|
if (projectProvider && Providers[projectProvider]) {
|
|
102
118
|
return Providers[projectProvider];
|
|
103
119
|
}
|
|
104
|
-
const detection = detectAllProviders();
|
|
120
|
+
const detection = await detectAllProviders();
|
|
105
121
|
if (detection.claude.installed && !detection.gemini.installed) {
|
|
106
122
|
return ClaudeProvider;
|
|
107
123
|
}
|
|
@@ -110,12 +126,12 @@ function getActiveProvider(projectProvider) {
|
|
|
110
126
|
}
|
|
111
127
|
return ClaudeProvider;
|
|
112
128
|
}
|
|
113
|
-
function hasProviderConfig(provider) {
|
|
129
|
+
async function hasProviderConfig(provider) {
|
|
114
130
|
const config = Providers[provider];
|
|
115
131
|
if (!config.configDir) {
|
|
116
132
|
return false;
|
|
117
133
|
}
|
|
118
|
-
return
|
|
134
|
+
return fileExists(config.configDir);
|
|
119
135
|
}
|
|
120
136
|
function getProviderBranding(provider) {
|
|
121
137
|
const commitFooter = `Generated with [p/](https://www.prjct.app/)`;
|
|
@@ -131,46 +147,52 @@ function getProviderBranding(provider) {
|
|
|
131
147
|
signature: signatures[provider] || "\u26A1 prjct"
|
|
132
148
|
};
|
|
133
149
|
}
|
|
134
|
-
function detectCursorProject(projectRoot) {
|
|
150
|
+
async function detectCursorProject(projectRoot) {
|
|
135
151
|
const cursorDir = import_node_path2.default.join(projectRoot, ".cursor");
|
|
136
152
|
const rulesDir = import_node_path2.default.join(cursorDir, "rules");
|
|
137
153
|
const routerPath = import_node_path2.default.join(rulesDir, "prjct.mdc");
|
|
138
|
-
const detected =
|
|
139
|
-
|
|
154
|
+
const [detected, routerInstalled] = await Promise.all([
|
|
155
|
+
fileExists(cursorDir),
|
|
156
|
+
fileExists(routerPath)
|
|
157
|
+
]);
|
|
140
158
|
return {
|
|
141
159
|
detected,
|
|
142
160
|
routerInstalled,
|
|
143
161
|
projectRoot: detected ? projectRoot : void 0
|
|
144
162
|
};
|
|
145
163
|
}
|
|
146
|
-
function needsCursorRouterRegeneration(projectRoot) {
|
|
147
|
-
const detection = detectCursorProject(projectRoot);
|
|
164
|
+
async function needsCursorRouterRegeneration(projectRoot) {
|
|
165
|
+
const detection = await detectCursorProject(projectRoot);
|
|
148
166
|
return detection.detected && !detection.routerInstalled;
|
|
149
167
|
}
|
|
150
|
-
function detectWindsurfProject(projectRoot) {
|
|
168
|
+
async function detectWindsurfProject(projectRoot) {
|
|
151
169
|
const windsurfDir = import_node_path2.default.join(projectRoot, ".windsurf");
|
|
152
170
|
const rulesDir = import_node_path2.default.join(windsurfDir, "rules");
|
|
153
171
|
const routerPath = import_node_path2.default.join(rulesDir, "prjct.md");
|
|
154
|
-
const detected =
|
|
155
|
-
|
|
172
|
+
const [detected, routerInstalled] = await Promise.all([
|
|
173
|
+
fileExists(windsurfDir),
|
|
174
|
+
fileExists(routerPath)
|
|
175
|
+
]);
|
|
156
176
|
return {
|
|
157
177
|
detected,
|
|
158
178
|
routerInstalled,
|
|
159
179
|
projectRoot: detected ? projectRoot : void 0
|
|
160
180
|
};
|
|
161
181
|
}
|
|
162
|
-
function needsWindsurfRouterRegeneration(projectRoot) {
|
|
163
|
-
const detection = detectWindsurfProject(projectRoot);
|
|
182
|
+
async function needsWindsurfRouterRegeneration(projectRoot) {
|
|
183
|
+
const detection = await detectWindsurfProject(projectRoot);
|
|
164
184
|
return detection.detected && !detection.routerInstalled;
|
|
165
185
|
}
|
|
166
|
-
function detectAntigravity() {
|
|
186
|
+
async function detectAntigravity() {
|
|
167
187
|
const configPath = AntigravityProvider.configDir;
|
|
168
188
|
if (!configPath) {
|
|
169
189
|
return { installed: false, skillInstalled: false };
|
|
170
190
|
}
|
|
171
|
-
const installed = import_node_fs2.default.existsSync(configPath);
|
|
172
191
|
const skillPath = import_node_path2.default.join(configPath, "skills", "prjct", "SKILL.md");
|
|
173
|
-
const skillInstalled =
|
|
192
|
+
const [installed, skillInstalled] = await Promise.all([
|
|
193
|
+
fileExists(configPath),
|
|
194
|
+
fileExists(skillPath)
|
|
195
|
+
]);
|
|
174
196
|
return {
|
|
175
197
|
installed,
|
|
176
198
|
skillInstalled,
|
|
@@ -201,8 +223,8 @@ function getProjectCommandsPath(provider, projectRoot) {
|
|
|
201
223
|
const config = Providers[provider];
|
|
202
224
|
return import_node_path2.default.join(projectRoot, config.commandsDir);
|
|
203
225
|
}
|
|
204
|
-
function selectProvider() {
|
|
205
|
-
const detection = detectAllProviders();
|
|
226
|
+
async function selectProvider() {
|
|
227
|
+
const detection = await detectAllProviders();
|
|
206
228
|
const claudeInstalled = detection.claude.installed;
|
|
207
229
|
const geminiInstalled = detection.gemini.installed;
|
|
208
230
|
if (!claudeInstalled && !geminiInstalled) {
|
|
@@ -233,14 +255,16 @@ function selectProvider() {
|
|
|
233
255
|
detection
|
|
234
256
|
};
|
|
235
257
|
}
|
|
236
|
-
var import_node_child_process,
|
|
258
|
+
var import_node_child_process, import_node_os, import_node_path2, import_node_util, execAsync, ClaudeProvider, GeminiProvider, AntigravityProvider, CursorProvider, WindsurfProvider, Providers, ai_provider_default;
|
|
237
259
|
var init_ai_provider = __esm({
|
|
238
260
|
"core/infrastructure/ai-provider.ts"() {
|
|
239
261
|
"use strict";
|
|
240
262
|
import_node_child_process = require("node:child_process");
|
|
241
|
-
import_node_fs2 = __toESM(require("node:fs"));
|
|
242
263
|
import_node_os = __toESM(require("node:os"));
|
|
243
264
|
import_node_path2 = __toESM(require("node:path"));
|
|
265
|
+
import_node_util = require("node:util");
|
|
266
|
+
init_fs_helpers();
|
|
267
|
+
execAsync = (0, import_node_util.promisify)(import_node_child_process.exec);
|
|
244
268
|
ClaudeProvider = {
|
|
245
269
|
name: "claude",
|
|
246
270
|
displayName: "Claude Code",
|
|
@@ -402,7 +426,7 @@ __export(command_installer_exports, {
|
|
|
402
426
|
isRouterInstalled: () => isRouterInstalled
|
|
403
427
|
});
|
|
404
428
|
module.exports = __toCommonJS(command_installer_exports);
|
|
405
|
-
var
|
|
429
|
+
var import_promises2 = __toESM(require("node:fs/promises"));
|
|
406
430
|
var import_node_os2 = __toESM(require("node:os"));
|
|
407
431
|
var import_node_path3 = __toESM(require("node:path"));
|
|
408
432
|
|
|
@@ -464,7 +488,7 @@ var PACKAGE_ROOT = getPackageRoot();
|
|
|
464
488
|
async function loadModuleConfig() {
|
|
465
489
|
try {
|
|
466
490
|
const configPath = import_node_path3.default.join(getPackageRoot(), "templates/global/modules/module-config.json");
|
|
467
|
-
const content = await
|
|
491
|
+
const content = await import_promises2.default.readFile(configPath, "utf-8");
|
|
468
492
|
return JSON.parse(content);
|
|
469
493
|
} catch {
|
|
470
494
|
return null;
|
|
@@ -476,7 +500,7 @@ async function composeGlobalTemplate(profile) {
|
|
|
476
500
|
const modulesDir = import_node_path3.default.join(getPackageRoot(), "templates/global/modules");
|
|
477
501
|
if (!config) {
|
|
478
502
|
const legacyPath = import_node_path3.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
|
|
479
|
-
return
|
|
503
|
+
return import_promises2.default.readFile(legacyPath, "utf-8");
|
|
480
504
|
}
|
|
481
505
|
const profileName = profile || config.default;
|
|
482
506
|
const selectedProfile = config.profiles[profileName];
|
|
@@ -484,7 +508,7 @@ async function composeGlobalTemplate(profile) {
|
|
|
484
508
|
const defaultProfile = config.profiles[config.default];
|
|
485
509
|
if (!defaultProfile) {
|
|
486
510
|
const legacyPath = import_node_path3.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
|
|
487
|
-
return
|
|
511
|
+
return import_promises2.default.readFile(legacyPath, "utf-8");
|
|
488
512
|
}
|
|
489
513
|
}
|
|
490
514
|
const modules = (selectedProfile || config.profiles[config.default]).modules;
|
|
@@ -493,7 +517,7 @@ async function composeGlobalTemplate(profile) {
|
|
|
493
517
|
for (const moduleName of modules) {
|
|
494
518
|
try {
|
|
495
519
|
const modulePath = import_node_path3.default.join(modulesDir, moduleName);
|
|
496
|
-
const content = await
|
|
520
|
+
const content = await import_promises2.default.readFile(modulePath, "utf-8");
|
|
497
521
|
parts.push("");
|
|
498
522
|
parts.push(content);
|
|
499
523
|
} catch {
|
|
@@ -516,14 +540,14 @@ async function installDocs() {
|
|
|
516
540
|
try {
|
|
517
541
|
const docsDir = import_node_path3.default.join(import_node_os2.default.homedir(), ".prjct-cli", "docs");
|
|
518
542
|
const templateDocsDir = import_node_path3.default.join(getPackageRoot(), "templates/global/docs");
|
|
519
|
-
await
|
|
520
|
-
const docFiles = await
|
|
543
|
+
await import_promises2.default.mkdir(docsDir, { recursive: true });
|
|
544
|
+
const docFiles = await import_promises2.default.readdir(templateDocsDir);
|
|
521
545
|
for (const file of docFiles) {
|
|
522
546
|
if (file.endsWith(".md")) {
|
|
523
547
|
const srcPath = import_node_path3.default.join(templateDocsDir, file);
|
|
524
548
|
const destPath = import_node_path3.default.join(docsDir, file);
|
|
525
|
-
const content = await
|
|
526
|
-
await
|
|
549
|
+
const content = await import_promises2.default.readFile(srcPath, "utf-8");
|
|
550
|
+
await import_promises2.default.writeFile(destPath, content, "utf-8");
|
|
527
551
|
}
|
|
528
552
|
}
|
|
529
553
|
return { success: true };
|
|
@@ -534,9 +558,9 @@ async function installDocs() {
|
|
|
534
558
|
__name(installDocs, "installDocs");
|
|
535
559
|
async function installGlobalConfig() {
|
|
536
560
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
537
|
-
const activeProvider = aiProvider.getActiveProvider();
|
|
561
|
+
const activeProvider = await aiProvider.getActiveProvider();
|
|
538
562
|
const providerName = activeProvider.name;
|
|
539
|
-
const detection = aiProvider.detectProvider(providerName);
|
|
563
|
+
const detection = await aiProvider.detectProvider(providerName);
|
|
540
564
|
if (!detection.installed && !activeProvider.configDir) {
|
|
541
565
|
return {
|
|
542
566
|
success: false,
|
|
@@ -545,7 +569,7 @@ async function installGlobalConfig() {
|
|
|
545
569
|
};
|
|
546
570
|
}
|
|
547
571
|
try {
|
|
548
|
-
await
|
|
572
|
+
await import_promises2.default.mkdir(activeProvider.configDir, { recursive: true });
|
|
549
573
|
const globalConfigPath = import_node_path3.default.join(activeProvider.configDir, activeProvider.contextFile);
|
|
550
574
|
const templatePath = import_node_path3.default.join(
|
|
551
575
|
getPackageRoot(),
|
|
@@ -555,37 +579,37 @@ async function installGlobalConfig() {
|
|
|
555
579
|
);
|
|
556
580
|
let templateContent = "";
|
|
557
581
|
try {
|
|
558
|
-
templateContent = await
|
|
582
|
+
templateContent = await import_promises2.default.readFile(templatePath, "utf-8");
|
|
559
583
|
} catch (_error) {
|
|
560
584
|
if (providerName === "claude") {
|
|
561
585
|
try {
|
|
562
586
|
templateContent = await composeGlobalTemplate("standard");
|
|
563
587
|
} catch {
|
|
564
588
|
const fallbackTemplatePath = import_node_path3.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
|
|
565
|
-
templateContent = await
|
|
589
|
+
templateContent = await import_promises2.default.readFile(fallbackTemplatePath, "utf-8");
|
|
566
590
|
}
|
|
567
591
|
} else {
|
|
568
592
|
const fallbackTemplatePath = import_node_path3.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
|
|
569
|
-
templateContent = await
|
|
593
|
+
templateContent = await import_promises2.default.readFile(fallbackTemplatePath, "utf-8");
|
|
570
594
|
if (providerName === "gemini") {
|
|
571
595
|
templateContent = templateContent.replace(/Claude/g, "Gemini");
|
|
572
596
|
}
|
|
573
597
|
}
|
|
574
598
|
}
|
|
575
599
|
let existingContent = "";
|
|
576
|
-
let
|
|
600
|
+
let fileExists2 = false;
|
|
577
601
|
try {
|
|
578
|
-
existingContent = await
|
|
579
|
-
|
|
602
|
+
existingContent = await import_promises2.default.readFile(globalConfigPath, "utf-8");
|
|
603
|
+
fileExists2 = true;
|
|
580
604
|
} catch (error) {
|
|
581
605
|
if (isNotFoundError(error)) {
|
|
582
|
-
|
|
606
|
+
fileExists2 = false;
|
|
583
607
|
} else {
|
|
584
608
|
throw error;
|
|
585
609
|
}
|
|
586
610
|
}
|
|
587
|
-
if (!
|
|
588
|
-
await
|
|
611
|
+
if (!fileExists2) {
|
|
612
|
+
await import_promises2.default.writeFile(globalConfigPath, templateContent, "utf-8");
|
|
589
613
|
return {
|
|
590
614
|
success: true,
|
|
591
615
|
action: "created",
|
|
@@ -599,7 +623,7 @@ async function installGlobalConfig() {
|
|
|
599
623
|
const updatedContent = `${existingContent}
|
|
600
624
|
|
|
601
625
|
${templateContent}`;
|
|
602
|
-
await
|
|
626
|
+
await import_promises2.default.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
603
627
|
return {
|
|
604
628
|
success: true,
|
|
605
629
|
action: "appended",
|
|
@@ -615,7 +639,7 @@ ${templateContent}`;
|
|
|
615
639
|
templateContent.indexOf(endMarker) + endMarker.length
|
|
616
640
|
);
|
|
617
641
|
const updatedContent = beforeMarker + prjctSection + afterMarker;
|
|
618
|
-
await
|
|
642
|
+
await import_promises2.default.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
619
643
|
return {
|
|
620
644
|
success: true,
|
|
621
645
|
action: "updated",
|
|
@@ -637,27 +661,33 @@ var CommandInstaller = class {
|
|
|
637
661
|
__name(this, "CommandInstaller");
|
|
638
662
|
}
|
|
639
663
|
homeDir;
|
|
640
|
-
claudeCommandsPath;
|
|
641
|
-
claudeConfigPath;
|
|
664
|
+
claudeCommandsPath = "";
|
|
665
|
+
claudeConfigPath = "";
|
|
642
666
|
templatesDir;
|
|
667
|
+
_initialized = false;
|
|
643
668
|
constructor() {
|
|
644
669
|
this.homeDir = import_node_os2.default.homedir();
|
|
670
|
+
this.templatesDir = import_node_path3.default.join(getPackageRoot(), "templates", "commands");
|
|
671
|
+
}
|
|
672
|
+
async ensureInit() {
|
|
673
|
+
if (this._initialized) return;
|
|
645
674
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
646
|
-
const activeProvider = aiProvider.getActiveProvider();
|
|
675
|
+
const activeProvider = await aiProvider.getActiveProvider();
|
|
647
676
|
if (activeProvider.name === "gemini") {
|
|
648
677
|
this.claudeCommandsPath = import_node_path3.default.join(activeProvider.configDir, "commands");
|
|
649
678
|
} else {
|
|
650
679
|
this.claudeCommandsPath = import_node_path3.default.join(activeProvider.configDir, "commands", "p");
|
|
651
680
|
}
|
|
652
681
|
this.claudeConfigPath = activeProvider.configDir;
|
|
653
|
-
this.
|
|
682
|
+
this._initialized = true;
|
|
654
683
|
}
|
|
655
684
|
/**
|
|
656
685
|
* Detect if active provider is installed
|
|
657
686
|
*/
|
|
658
687
|
async detectActiveProvider() {
|
|
688
|
+
await this.ensureInit();
|
|
659
689
|
try {
|
|
660
|
-
await
|
|
690
|
+
await import_promises2.default.access(this.claudeConfigPath);
|
|
661
691
|
return true;
|
|
662
692
|
} catch (error) {
|
|
663
693
|
if (isNotFoundError(error)) {
|
|
@@ -677,7 +707,7 @@ var CommandInstaller = class {
|
|
|
677
707
|
*/
|
|
678
708
|
async getCommandFiles() {
|
|
679
709
|
try {
|
|
680
|
-
const files = await
|
|
710
|
+
const files = await import_promises2.default.readdir(this.templatesDir);
|
|
681
711
|
return files.filter((f) => f.endsWith(".md"));
|
|
682
712
|
} catch (_error) {
|
|
683
713
|
return [
|
|
@@ -709,7 +739,7 @@ var CommandInstaller = class {
|
|
|
709
739
|
async installCommands() {
|
|
710
740
|
const providerDetected = await this.detectActiveProvider();
|
|
711
741
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
712
|
-
const activeProvider = aiProvider.getActiveProvider();
|
|
742
|
+
const activeProvider = await aiProvider.getActiveProvider();
|
|
713
743
|
if (!providerDetected) {
|
|
714
744
|
return {
|
|
715
745
|
success: false,
|
|
@@ -718,7 +748,7 @@ var CommandInstaller = class {
|
|
|
718
748
|
}
|
|
719
749
|
try {
|
|
720
750
|
await this.installRouter();
|
|
721
|
-
await
|
|
751
|
+
await import_promises2.default.mkdir(this.claudeCommandsPath, { recursive: true });
|
|
722
752
|
const commandFiles = await this.getCommandFiles();
|
|
723
753
|
const installed = [];
|
|
724
754
|
const errors = [];
|
|
@@ -726,8 +756,8 @@ var CommandInstaller = class {
|
|
|
726
756
|
try {
|
|
727
757
|
const sourcePath = import_node_path3.default.join(this.templatesDir, file);
|
|
728
758
|
const destPath = import_node_path3.default.join(this.claudeCommandsPath, file);
|
|
729
|
-
const content = await
|
|
730
|
-
await
|
|
759
|
+
const content = await import_promises2.default.readFile(sourcePath, "utf-8");
|
|
760
|
+
await import_promises2.default.writeFile(destPath, content, "utf-8");
|
|
731
761
|
installed.push(file.replace(".md", ""));
|
|
732
762
|
} catch (error) {
|
|
733
763
|
errors.push({ file, error: error.message });
|
|
@@ -757,7 +787,7 @@ var CommandInstaller = class {
|
|
|
757
787
|
for (const file of commandFiles) {
|
|
758
788
|
try {
|
|
759
789
|
const filePath = import_node_path3.default.join(this.claudeCommandsPath, file);
|
|
760
|
-
await
|
|
790
|
+
await import_promises2.default.unlink(filePath);
|
|
761
791
|
uninstalled.push(file.replace(".md", ""));
|
|
762
792
|
} catch (error) {
|
|
763
793
|
if (error.code !== "ENOENT") {
|
|
@@ -766,7 +796,7 @@ var CommandInstaller = class {
|
|
|
766
796
|
}
|
|
767
797
|
}
|
|
768
798
|
try {
|
|
769
|
-
await
|
|
799
|
+
await import_promises2.default.rmdir(this.claudeCommandsPath);
|
|
770
800
|
} catch (_error) {
|
|
771
801
|
}
|
|
772
802
|
return {
|
|
@@ -793,8 +823,8 @@ var CommandInstaller = class {
|
|
|
793
823
|
};
|
|
794
824
|
}
|
|
795
825
|
try {
|
|
796
|
-
await
|
|
797
|
-
const files = await
|
|
826
|
+
await import_promises2.default.access(this.claudeCommandsPath);
|
|
827
|
+
const files = await import_promises2.default.readdir(this.claudeCommandsPath);
|
|
798
828
|
const installedCommands = files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
|
|
799
829
|
return {
|
|
800
830
|
installed: installedCommands.length > 0,
|
|
@@ -833,7 +863,8 @@ var CommandInstaller = class {
|
|
|
833
863
|
/**
|
|
834
864
|
* Get installation path for Claude commands
|
|
835
865
|
*/
|
|
836
|
-
getInstallPath() {
|
|
866
|
+
async getInstallPath() {
|
|
867
|
+
await this.ensureInit();
|
|
837
868
|
return this.claudeCommandsPath;
|
|
838
869
|
}
|
|
839
870
|
/**
|
|
@@ -842,7 +873,7 @@ var CommandInstaller = class {
|
|
|
842
873
|
async verifyTemplate(commandName) {
|
|
843
874
|
try {
|
|
844
875
|
const templatePath = import_node_path3.default.join(this.templatesDir, `${commandName}.md`);
|
|
845
|
-
await
|
|
876
|
+
await import_promises2.default.access(templatePath);
|
|
846
877
|
return true;
|
|
847
878
|
} catch (error) {
|
|
848
879
|
if (isNotFoundError(error)) {
|
|
@@ -857,14 +888,14 @@ var CommandInstaller = class {
|
|
|
857
888
|
*/
|
|
858
889
|
async installRouter() {
|
|
859
890
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
860
|
-
const activeProvider = aiProvider.getActiveProvider();
|
|
891
|
+
const activeProvider = await aiProvider.getActiveProvider();
|
|
861
892
|
const routerFile = activeProvider.name === "gemini" ? "p.toml" : "p.md";
|
|
862
893
|
try {
|
|
863
894
|
const routerSource = import_node_path3.default.join(this.templatesDir, routerFile);
|
|
864
895
|
const routerDest = import_node_path3.default.join(activeProvider.configDir, "commands", routerFile);
|
|
865
|
-
await
|
|
866
|
-
const content = await
|
|
867
|
-
await
|
|
896
|
+
await import_promises2.default.mkdir(import_node_path3.default.dirname(routerDest), { recursive: true });
|
|
897
|
+
const content = await import_promises2.default.readFile(routerSource, "utf-8");
|
|
898
|
+
await import_promises2.default.writeFile(routerDest, content, "utf-8");
|
|
868
899
|
return true;
|
|
869
900
|
} catch (error) {
|
|
870
901
|
if (isNotFoundError(error)) {
|
|
@@ -879,15 +910,15 @@ var CommandInstaller = class {
|
|
|
879
910
|
*/
|
|
880
911
|
async removeLegacyCommands() {
|
|
881
912
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
882
|
-
const activeProvider = aiProvider.getActiveProvider();
|
|
913
|
+
const activeProvider = await aiProvider.getActiveProvider();
|
|
883
914
|
const commandsRoot = import_node_path3.default.join(activeProvider.configDir, "commands");
|
|
884
915
|
let removed = 0;
|
|
885
916
|
try {
|
|
886
|
-
const files = await
|
|
917
|
+
const files = await import_promises2.default.readdir(commandsRoot);
|
|
887
918
|
const legacyFiles = files.filter((f) => f.startsWith("p.") && f.endsWith(".md"));
|
|
888
919
|
for (const file of legacyFiles) {
|
|
889
920
|
try {
|
|
890
|
-
await
|
|
921
|
+
await import_promises2.default.unlink(import_node_path3.default.join(commandsRoot, file));
|
|
891
922
|
removed++;
|
|
892
923
|
} catch {
|
|
893
924
|
}
|
|
@@ -912,11 +943,11 @@ var CommandInstaller = class {
|
|
|
912
943
|
}
|
|
913
944
|
try {
|
|
914
945
|
await this.installRouter();
|
|
915
|
-
await
|
|
946
|
+
await import_promises2.default.mkdir(this.claudeCommandsPath, { recursive: true });
|
|
916
947
|
const templateFiles = await this.getCommandFiles();
|
|
917
948
|
let installedFiles = [];
|
|
918
949
|
try {
|
|
919
|
-
installedFiles = await
|
|
950
|
+
installedFiles = await import_promises2.default.readdir(this.claudeCommandsPath);
|
|
920
951
|
installedFiles = installedFiles.filter((f) => f.endsWith(".md"));
|
|
921
952
|
} catch (error) {
|
|
922
953
|
if (isNotFoundError(error)) {
|
|
@@ -937,8 +968,8 @@ var CommandInstaller = class {
|
|
|
937
968
|
const sourcePath = import_node_path3.default.join(this.templatesDir, file);
|
|
938
969
|
const destPath = import_node_path3.default.join(this.claudeCommandsPath, file);
|
|
939
970
|
const exists = installedFiles.includes(file);
|
|
940
|
-
const content = await
|
|
941
|
-
await
|
|
971
|
+
const content = await import_promises2.default.readFile(sourcePath, "utf-8");
|
|
972
|
+
await import_promises2.default.writeFile(destPath, content, "utf-8");
|
|
942
973
|
if (!exists) {
|
|
943
974
|
results.added++;
|
|
944
975
|
} else {
|
|
@@ -993,7 +1024,7 @@ async function isRouterInstalled(provider) {
|
|
|
993
1024
|
const paths = getProviderPaths();
|
|
994
1025
|
const routerPath = paths[provider].router;
|
|
995
1026
|
try {
|
|
996
|
-
await
|
|
1027
|
+
await import_promises2.default.access(routerPath);
|
|
997
1028
|
return true;
|
|
998
1029
|
} catch {
|
|
999
1030
|
return false;
|