prjct-cli 1.6.10 → 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 +34 -1
- package/bin/prjct.ts +11 -2
- package/core/infrastructure/ai-provider.ts +17 -5
- package/core/utils/provider-cache.ts +49 -0
- package/dist/bin/prjct.mjs +1103 -1044
- 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_process2,
|
|
300
|
+
var import_node_child_process2, 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_process2 = 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_process2.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",
|
|
@@ -403,9 +448,9 @@ __export(setup_exports, {
|
|
|
403
448
|
});
|
|
404
449
|
module.exports = __toCommonJS(setup_exports);
|
|
405
450
|
var import_node_child_process3 = require("node:child_process");
|
|
406
|
-
var
|
|
407
|
-
var
|
|
408
|
-
var
|
|
451
|
+
var import_promises5 = __toESM(require("node:fs/promises"));
|
|
452
|
+
var import_node_os5 = __toESM(require("node:os"));
|
|
453
|
+
var import_node_path6 = __toESM(require("node:path"));
|
|
409
454
|
var import_chalk = __toESM(require("chalk"));
|
|
410
455
|
|
|
411
456
|
// core/constants/index.ts
|
|
@@ -788,13 +833,13 @@ var PACKAGE_ROOT = getPackageRoot();
|
|
|
788
833
|
init_ai_provider();
|
|
789
834
|
|
|
790
835
|
// core/infrastructure/command-installer.ts
|
|
791
|
-
var
|
|
792
|
-
var
|
|
793
|
-
var
|
|
836
|
+
var import_promises3 = __toESM(require("node:fs/promises"));
|
|
837
|
+
var import_node_os3 = __toESM(require("node:os"));
|
|
838
|
+
var import_node_path4 = __toESM(require("node:path"));
|
|
794
839
|
async function loadModuleConfig() {
|
|
795
840
|
try {
|
|
796
|
-
const configPath =
|
|
797
|
-
const content = await
|
|
841
|
+
const configPath = import_node_path4.default.join(getPackageRoot(), "templates/global/modules/module-config.json");
|
|
842
|
+
const content = await import_promises3.default.readFile(configPath, "utf-8");
|
|
798
843
|
return JSON.parse(content);
|
|
799
844
|
} catch {
|
|
800
845
|
return null;
|
|
@@ -803,18 +848,18 @@ async function loadModuleConfig() {
|
|
|
803
848
|
__name(loadModuleConfig, "loadModuleConfig");
|
|
804
849
|
async function composeGlobalTemplate(profile) {
|
|
805
850
|
const config = await loadModuleConfig();
|
|
806
|
-
const modulesDir =
|
|
851
|
+
const modulesDir = import_node_path4.default.join(getPackageRoot(), "templates/global/modules");
|
|
807
852
|
if (!config) {
|
|
808
|
-
const legacyPath =
|
|
809
|
-
return
|
|
853
|
+
const legacyPath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
|
|
854
|
+
return import_promises3.default.readFile(legacyPath, "utf-8");
|
|
810
855
|
}
|
|
811
856
|
const profileName = profile || config.default;
|
|
812
857
|
const selectedProfile = config.profiles[profileName];
|
|
813
858
|
if (!selectedProfile) {
|
|
814
859
|
const defaultProfile = config.profiles[config.default];
|
|
815
860
|
if (!defaultProfile) {
|
|
816
|
-
const legacyPath =
|
|
817
|
-
return
|
|
861
|
+
const legacyPath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
|
|
862
|
+
return import_promises3.default.readFile(legacyPath, "utf-8");
|
|
818
863
|
}
|
|
819
864
|
}
|
|
820
865
|
const modules = (selectedProfile || config.profiles[config.default]).modules;
|
|
@@ -822,8 +867,8 @@ async function composeGlobalTemplate(profile) {
|
|
|
822
867
|
parts.push("<!-- prjct:start - DO NOT REMOVE THIS MARKER -->");
|
|
823
868
|
for (const moduleName of modules) {
|
|
824
869
|
try {
|
|
825
|
-
const modulePath =
|
|
826
|
-
const content = await
|
|
870
|
+
const modulePath = import_node_path4.default.join(modulesDir, moduleName);
|
|
871
|
+
const content = await import_promises3.default.readFile(modulePath, "utf-8");
|
|
827
872
|
parts.push("");
|
|
828
873
|
parts.push(content);
|
|
829
874
|
} catch {
|
|
@@ -838,16 +883,16 @@ async function composeGlobalTemplate(profile) {
|
|
|
838
883
|
__name(composeGlobalTemplate, "composeGlobalTemplate");
|
|
839
884
|
async function installDocs() {
|
|
840
885
|
try {
|
|
841
|
-
const docsDir =
|
|
842
|
-
const templateDocsDir =
|
|
843
|
-
await
|
|
844
|
-
const docFiles = await
|
|
886
|
+
const docsDir = import_node_path4.default.join(import_node_os3.default.homedir(), ".prjct-cli", "docs");
|
|
887
|
+
const templateDocsDir = import_node_path4.default.join(getPackageRoot(), "templates/global/docs");
|
|
888
|
+
await import_promises3.default.mkdir(docsDir, { recursive: true });
|
|
889
|
+
const docFiles = await import_promises3.default.readdir(templateDocsDir);
|
|
845
890
|
for (const file of docFiles) {
|
|
846
891
|
if (file.endsWith(".md")) {
|
|
847
|
-
const srcPath =
|
|
848
|
-
const destPath =
|
|
849
|
-
const content = await
|
|
850
|
-
await
|
|
892
|
+
const srcPath = import_node_path4.default.join(templateDocsDir, file);
|
|
893
|
+
const destPath = import_node_path4.default.join(docsDir, file);
|
|
894
|
+
const content = await import_promises3.default.readFile(srcPath, "utf-8");
|
|
895
|
+
await import_promises3.default.writeFile(destPath, content, "utf-8");
|
|
851
896
|
}
|
|
852
897
|
}
|
|
853
898
|
return { success: true };
|
|
@@ -869,9 +914,9 @@ async function installGlobalConfig() {
|
|
|
869
914
|
};
|
|
870
915
|
}
|
|
871
916
|
try {
|
|
872
|
-
await
|
|
873
|
-
const globalConfigPath =
|
|
874
|
-
const templatePath =
|
|
917
|
+
await import_promises3.default.mkdir(activeProvider.configDir, { recursive: true });
|
|
918
|
+
const globalConfigPath = import_node_path4.default.join(activeProvider.configDir, activeProvider.contextFile);
|
|
919
|
+
const templatePath = import_node_path4.default.join(
|
|
875
920
|
getPackageRoot(),
|
|
876
921
|
"templates",
|
|
877
922
|
"global",
|
|
@@ -879,18 +924,18 @@ async function installGlobalConfig() {
|
|
|
879
924
|
);
|
|
880
925
|
let templateContent = "";
|
|
881
926
|
try {
|
|
882
|
-
templateContent = await
|
|
927
|
+
templateContent = await import_promises3.default.readFile(templatePath, "utf-8");
|
|
883
928
|
} catch (_error) {
|
|
884
929
|
if (providerName === "claude") {
|
|
885
930
|
try {
|
|
886
931
|
templateContent = await composeGlobalTemplate("standard");
|
|
887
932
|
} catch {
|
|
888
|
-
const fallbackTemplatePath =
|
|
889
|
-
templateContent = await
|
|
933
|
+
const fallbackTemplatePath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
|
|
934
|
+
templateContent = await import_promises3.default.readFile(fallbackTemplatePath, "utf-8");
|
|
890
935
|
}
|
|
891
936
|
} else {
|
|
892
|
-
const fallbackTemplatePath =
|
|
893
|
-
templateContent = await
|
|
937
|
+
const fallbackTemplatePath = import_node_path4.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
|
|
938
|
+
templateContent = await import_promises3.default.readFile(fallbackTemplatePath, "utf-8");
|
|
894
939
|
if (providerName === "gemini") {
|
|
895
940
|
templateContent = templateContent.replace(/Claude/g, "Gemini");
|
|
896
941
|
}
|
|
@@ -899,7 +944,7 @@ async function installGlobalConfig() {
|
|
|
899
944
|
let existingContent = "";
|
|
900
945
|
let fileExists2 = false;
|
|
901
946
|
try {
|
|
902
|
-
existingContent = await
|
|
947
|
+
existingContent = await import_promises3.default.readFile(globalConfigPath, "utf-8");
|
|
903
948
|
fileExists2 = true;
|
|
904
949
|
} catch (error) {
|
|
905
950
|
if (isNotFoundError(error)) {
|
|
@@ -909,7 +954,7 @@ async function installGlobalConfig() {
|
|
|
909
954
|
}
|
|
910
955
|
}
|
|
911
956
|
if (!fileExists2) {
|
|
912
|
-
await
|
|
957
|
+
await import_promises3.default.writeFile(globalConfigPath, templateContent, "utf-8");
|
|
913
958
|
return {
|
|
914
959
|
success: true,
|
|
915
960
|
action: "created",
|
|
@@ -923,7 +968,7 @@ async function installGlobalConfig() {
|
|
|
923
968
|
const updatedContent = `${existingContent}
|
|
924
969
|
|
|
925
970
|
${templateContent}`;
|
|
926
|
-
await
|
|
971
|
+
await import_promises3.default.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
927
972
|
return {
|
|
928
973
|
success: true,
|
|
929
974
|
action: "appended",
|
|
@@ -939,7 +984,7 @@ ${templateContent}`;
|
|
|
939
984
|
templateContent.indexOf(endMarker) + endMarker.length
|
|
940
985
|
);
|
|
941
986
|
const updatedContent = beforeMarker + prjctSection + afterMarker;
|
|
942
|
-
await
|
|
987
|
+
await import_promises3.default.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
943
988
|
return {
|
|
944
989
|
success: true,
|
|
945
990
|
action: "updated",
|
|
@@ -966,17 +1011,17 @@ var CommandInstaller = class {
|
|
|
966
1011
|
templatesDir;
|
|
967
1012
|
_initialized = false;
|
|
968
1013
|
constructor() {
|
|
969
|
-
this.homeDir =
|
|
970
|
-
this.templatesDir =
|
|
1014
|
+
this.homeDir = import_node_os3.default.homedir();
|
|
1015
|
+
this.templatesDir = import_node_path4.default.join(getPackageRoot(), "templates", "commands");
|
|
971
1016
|
}
|
|
972
1017
|
async ensureInit() {
|
|
973
1018
|
if (this._initialized) return;
|
|
974
1019
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
975
1020
|
const activeProvider = await aiProvider.getActiveProvider();
|
|
976
1021
|
if (activeProvider.name === "gemini") {
|
|
977
|
-
this.claudeCommandsPath =
|
|
1022
|
+
this.claudeCommandsPath = import_node_path4.default.join(activeProvider.configDir, "commands");
|
|
978
1023
|
} else {
|
|
979
|
-
this.claudeCommandsPath =
|
|
1024
|
+
this.claudeCommandsPath = import_node_path4.default.join(activeProvider.configDir, "commands", "p");
|
|
980
1025
|
}
|
|
981
1026
|
this.claudeConfigPath = activeProvider.configDir;
|
|
982
1027
|
this._initialized = true;
|
|
@@ -987,7 +1032,7 @@ var CommandInstaller = class {
|
|
|
987
1032
|
async detectActiveProvider() {
|
|
988
1033
|
await this.ensureInit();
|
|
989
1034
|
try {
|
|
990
|
-
await
|
|
1035
|
+
await import_promises3.default.access(this.claudeConfigPath);
|
|
991
1036
|
return true;
|
|
992
1037
|
} catch (error) {
|
|
993
1038
|
if (isNotFoundError(error)) {
|
|
@@ -1007,7 +1052,7 @@ var CommandInstaller = class {
|
|
|
1007
1052
|
*/
|
|
1008
1053
|
async getCommandFiles() {
|
|
1009
1054
|
try {
|
|
1010
|
-
const files = await
|
|
1055
|
+
const files = await import_promises3.default.readdir(this.templatesDir);
|
|
1011
1056
|
return files.filter((f) => f.endsWith(".md"));
|
|
1012
1057
|
} catch (_error) {
|
|
1013
1058
|
return [
|
|
@@ -1048,16 +1093,16 @@ var CommandInstaller = class {
|
|
|
1048
1093
|
}
|
|
1049
1094
|
try {
|
|
1050
1095
|
await this.installRouter();
|
|
1051
|
-
await
|
|
1096
|
+
await import_promises3.default.mkdir(this.claudeCommandsPath, { recursive: true });
|
|
1052
1097
|
const commandFiles = await this.getCommandFiles();
|
|
1053
1098
|
const installed = [];
|
|
1054
1099
|
const errors = [];
|
|
1055
1100
|
for (const file of commandFiles) {
|
|
1056
1101
|
try {
|
|
1057
|
-
const sourcePath =
|
|
1058
|
-
const destPath =
|
|
1059
|
-
const content = await
|
|
1060
|
-
await
|
|
1102
|
+
const sourcePath = import_node_path4.default.join(this.templatesDir, file);
|
|
1103
|
+
const destPath = import_node_path4.default.join(this.claudeCommandsPath, file);
|
|
1104
|
+
const content = await import_promises3.default.readFile(sourcePath, "utf-8");
|
|
1105
|
+
await import_promises3.default.writeFile(destPath, content, "utf-8");
|
|
1061
1106
|
installed.push(file.replace(".md", ""));
|
|
1062
1107
|
} catch (error) {
|
|
1063
1108
|
errors.push({ file, error: getErrorMessage(error) });
|
|
@@ -1086,8 +1131,8 @@ var CommandInstaller = class {
|
|
|
1086
1131
|
const errors = [];
|
|
1087
1132
|
for (const file of commandFiles) {
|
|
1088
1133
|
try {
|
|
1089
|
-
const filePath =
|
|
1090
|
-
await
|
|
1134
|
+
const filePath = import_node_path4.default.join(this.claudeCommandsPath, file);
|
|
1135
|
+
await import_promises3.default.unlink(filePath);
|
|
1091
1136
|
uninstalled.push(file.replace(".md", ""));
|
|
1092
1137
|
} catch (error) {
|
|
1093
1138
|
if (error.code !== "ENOENT") {
|
|
@@ -1096,7 +1141,7 @@ var CommandInstaller = class {
|
|
|
1096
1141
|
}
|
|
1097
1142
|
}
|
|
1098
1143
|
try {
|
|
1099
|
-
await
|
|
1144
|
+
await import_promises3.default.rmdir(this.claudeCommandsPath);
|
|
1100
1145
|
} catch (_error) {
|
|
1101
1146
|
}
|
|
1102
1147
|
return {
|
|
@@ -1123,8 +1168,8 @@ var CommandInstaller = class {
|
|
|
1123
1168
|
};
|
|
1124
1169
|
}
|
|
1125
1170
|
try {
|
|
1126
|
-
await
|
|
1127
|
-
const files = await
|
|
1171
|
+
await import_promises3.default.access(this.claudeCommandsPath);
|
|
1172
|
+
const files = await import_promises3.default.readdir(this.claudeCommandsPath);
|
|
1128
1173
|
const installedCommands = files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
|
|
1129
1174
|
return {
|
|
1130
1175
|
installed: installedCommands.length > 0,
|
|
@@ -1172,8 +1217,8 @@ var CommandInstaller = class {
|
|
|
1172
1217
|
*/
|
|
1173
1218
|
async verifyTemplate(commandName) {
|
|
1174
1219
|
try {
|
|
1175
|
-
const templatePath =
|
|
1176
|
-
await
|
|
1220
|
+
const templatePath = import_node_path4.default.join(this.templatesDir, `${commandName}.md`);
|
|
1221
|
+
await import_promises3.default.access(templatePath);
|
|
1177
1222
|
return true;
|
|
1178
1223
|
} catch (error) {
|
|
1179
1224
|
if (isNotFoundError(error)) {
|
|
@@ -1191,11 +1236,11 @@ var CommandInstaller = class {
|
|
|
1191
1236
|
const activeProvider = await aiProvider.getActiveProvider();
|
|
1192
1237
|
const routerFile = activeProvider.name === "gemini" ? "p.toml" : "p.md";
|
|
1193
1238
|
try {
|
|
1194
|
-
const routerSource =
|
|
1195
|
-
const routerDest =
|
|
1196
|
-
await
|
|
1197
|
-
const content = await
|
|
1198
|
-
await
|
|
1239
|
+
const routerSource = import_node_path4.default.join(this.templatesDir, routerFile);
|
|
1240
|
+
const routerDest = import_node_path4.default.join(activeProvider.configDir, "commands", routerFile);
|
|
1241
|
+
await import_promises3.default.mkdir(import_node_path4.default.dirname(routerDest), { recursive: true });
|
|
1242
|
+
const content = await import_promises3.default.readFile(routerSource, "utf-8");
|
|
1243
|
+
await import_promises3.default.writeFile(routerDest, content, "utf-8");
|
|
1199
1244
|
return true;
|
|
1200
1245
|
} catch (error) {
|
|
1201
1246
|
if (isNotFoundError(error)) {
|
|
@@ -1211,14 +1256,14 @@ var CommandInstaller = class {
|
|
|
1211
1256
|
async removeLegacyCommands() {
|
|
1212
1257
|
const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
|
|
1213
1258
|
const activeProvider = await aiProvider.getActiveProvider();
|
|
1214
|
-
const commandsRoot =
|
|
1259
|
+
const commandsRoot = import_node_path4.default.join(activeProvider.configDir, "commands");
|
|
1215
1260
|
let removed = 0;
|
|
1216
1261
|
try {
|
|
1217
|
-
const files = await
|
|
1262
|
+
const files = await import_promises3.default.readdir(commandsRoot);
|
|
1218
1263
|
const legacyFiles = files.filter((f) => f.startsWith("p.") && f.endsWith(".md"));
|
|
1219
1264
|
for (const file of legacyFiles) {
|
|
1220
1265
|
try {
|
|
1221
|
-
await
|
|
1266
|
+
await import_promises3.default.unlink(import_node_path4.default.join(commandsRoot, file));
|
|
1222
1267
|
removed++;
|
|
1223
1268
|
} catch {
|
|
1224
1269
|
}
|
|
@@ -1243,11 +1288,11 @@ var CommandInstaller = class {
|
|
|
1243
1288
|
}
|
|
1244
1289
|
try {
|
|
1245
1290
|
await this.installRouter();
|
|
1246
|
-
await
|
|
1291
|
+
await import_promises3.default.mkdir(this.claudeCommandsPath, { recursive: true });
|
|
1247
1292
|
const templateFiles = await this.getCommandFiles();
|
|
1248
1293
|
let installedFiles = [];
|
|
1249
1294
|
try {
|
|
1250
|
-
installedFiles = await
|
|
1295
|
+
installedFiles = await import_promises3.default.readdir(this.claudeCommandsPath);
|
|
1251
1296
|
installedFiles = installedFiles.filter((f) => f.endsWith(".md"));
|
|
1252
1297
|
} catch (error) {
|
|
1253
1298
|
if (isNotFoundError(error)) {
|
|
@@ -1265,11 +1310,11 @@ var CommandInstaller = class {
|
|
|
1265
1310
|
};
|
|
1266
1311
|
for (const file of templateFiles) {
|
|
1267
1312
|
try {
|
|
1268
|
-
const sourcePath =
|
|
1269
|
-
const destPath =
|
|
1313
|
+
const sourcePath = import_node_path4.default.join(this.templatesDir, file);
|
|
1314
|
+
const destPath = import_node_path4.default.join(this.claudeCommandsPath, file);
|
|
1270
1315
|
const exists = installedFiles.includes(file);
|
|
1271
|
-
const content = await
|
|
1272
|
-
await
|
|
1316
|
+
const content = await import_promises3.default.readFile(sourcePath, "utf-8");
|
|
1317
|
+
await import_promises3.default.writeFile(destPath, content, "utf-8");
|
|
1273
1318
|
if (!exists) {
|
|
1274
1319
|
results.added++;
|
|
1275
1320
|
} else {
|
|
@@ -1308,9 +1353,9 @@ var commandInstaller = new CommandInstaller();
|
|
|
1308
1353
|
var command_installer_default = commandInstaller;
|
|
1309
1354
|
|
|
1310
1355
|
// core/infrastructure/editors-config.ts
|
|
1311
|
-
var
|
|
1312
|
-
var
|
|
1313
|
-
var
|
|
1356
|
+
var import_promises4 = __toESM(require("node:fs/promises"));
|
|
1357
|
+
var import_node_os4 = __toESM(require("node:os"));
|
|
1358
|
+
var import_node_path5 = __toESM(require("node:path"));
|
|
1314
1359
|
var EditorsConfig = class {
|
|
1315
1360
|
static {
|
|
1316
1361
|
__name(this, "EditorsConfig");
|
|
@@ -1319,16 +1364,16 @@ var EditorsConfig = class {
|
|
|
1319
1364
|
configDir;
|
|
1320
1365
|
configFile;
|
|
1321
1366
|
constructor() {
|
|
1322
|
-
this.homeDir =
|
|
1323
|
-
this.configDir =
|
|
1324
|
-
this.configFile =
|
|
1367
|
+
this.homeDir = import_node_os4.default.homedir();
|
|
1368
|
+
this.configDir = import_node_path5.default.join(this.homeDir, ".prjct-cli", "config");
|
|
1369
|
+
this.configFile = import_node_path5.default.join(this.configDir, "installed-editors.json");
|
|
1325
1370
|
}
|
|
1326
1371
|
/**
|
|
1327
1372
|
* Ensure config directory exists
|
|
1328
1373
|
*/
|
|
1329
1374
|
async ensureConfigDir() {
|
|
1330
1375
|
try {
|
|
1331
|
-
await
|
|
1376
|
+
await import_promises4.default.mkdir(this.configDir, { recursive: true });
|
|
1332
1377
|
} catch (error) {
|
|
1333
1378
|
console.error("[editors-config] Error creating config directory:", getErrorMessage(error));
|
|
1334
1379
|
}
|
|
@@ -1338,7 +1383,7 @@ var EditorsConfig = class {
|
|
|
1338
1383
|
*/
|
|
1339
1384
|
async loadConfig() {
|
|
1340
1385
|
try {
|
|
1341
|
-
const content = await
|
|
1386
|
+
const content = await import_promises4.default.readFile(this.configFile, "utf-8");
|
|
1342
1387
|
return JSON.parse(content);
|
|
1343
1388
|
} catch (error) {
|
|
1344
1389
|
if (error.code === "ENOENT") {
|
|
@@ -1362,7 +1407,7 @@ var EditorsConfig = class {
|
|
|
1362
1407
|
lastInstall: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1363
1408
|
path: installPath
|
|
1364
1409
|
};
|
|
1365
|
-
await
|
|
1410
|
+
await import_promises4.default.writeFile(this.configFile, JSON.stringify(config, null, 2), "utf-8");
|
|
1366
1411
|
return true;
|
|
1367
1412
|
} catch (error) {
|
|
1368
1413
|
console.error("[editors-config] Error saving config:", getErrorMessage(error));
|
|
@@ -1402,7 +1447,7 @@ var EditorsConfig = class {
|
|
|
1402
1447
|
}
|
|
1403
1448
|
config.version = version;
|
|
1404
1449
|
config.lastInstall = (/* @__PURE__ */ new Date()).toISOString();
|
|
1405
|
-
await
|
|
1450
|
+
await import_promises4.default.writeFile(this.configFile, JSON.stringify(config, null, 2), "utf-8");
|
|
1406
1451
|
return true;
|
|
1407
1452
|
} catch (error) {
|
|
1408
1453
|
console.error("[editors-config] Error updating version:", getErrorMessage(error));
|
|
@@ -1414,7 +1459,7 @@ var EditorsConfig = class {
|
|
|
1414
1459
|
*/
|
|
1415
1460
|
async configExists() {
|
|
1416
1461
|
try {
|
|
1417
|
-
await
|
|
1462
|
+
await import_promises4.default.access(this.configFile);
|
|
1418
1463
|
return true;
|
|
1419
1464
|
} catch (_error) {
|
|
1420
1465
|
return false;
|
|
@@ -1428,7 +1473,7 @@ var EditorsConfig = class {
|
|
|
1428
1473
|
try {
|
|
1429
1474
|
const exists = await this.configExists();
|
|
1430
1475
|
if (exists) {
|
|
1431
|
-
await
|
|
1476
|
+
await import_promises4.default.unlink(this.configFile);
|
|
1432
1477
|
}
|
|
1433
1478
|
return true;
|
|
1434
1479
|
} catch (error) {
|
|
@@ -1580,12 +1625,12 @@ async function run() {
|
|
|
1580
1625
|
__name(run, "run");
|
|
1581
1626
|
async function installGeminiRouter() {
|
|
1582
1627
|
try {
|
|
1583
|
-
const geminiCommandsDir =
|
|
1584
|
-
const routerSource =
|
|
1585
|
-
const routerDest =
|
|
1586
|
-
await
|
|
1628
|
+
const geminiCommandsDir = import_node_path6.default.join(import_node_os5.default.homedir(), ".gemini", "commands");
|
|
1629
|
+
const routerSource = import_node_path6.default.join(getPackageRoot(), "templates", "commands", "p.toml");
|
|
1630
|
+
const routerDest = import_node_path6.default.join(geminiCommandsDir, "p.toml");
|
|
1631
|
+
await import_promises5.default.mkdir(geminiCommandsDir, { recursive: true });
|
|
1587
1632
|
if (await fileExists(routerSource)) {
|
|
1588
|
-
await
|
|
1633
|
+
await import_promises5.default.copyFile(routerSource, routerDest);
|
|
1589
1634
|
return true;
|
|
1590
1635
|
}
|
|
1591
1636
|
return false;
|
|
@@ -1597,15 +1642,15 @@ async function installGeminiRouter() {
|
|
|
1597
1642
|
__name(installGeminiRouter, "installGeminiRouter");
|
|
1598
1643
|
async function installGeminiGlobalConfig() {
|
|
1599
1644
|
try {
|
|
1600
|
-
const geminiDir =
|
|
1601
|
-
const globalConfigPath =
|
|
1602
|
-
const templatePath =
|
|
1603
|
-
await
|
|
1604
|
-
const templateContent = await
|
|
1645
|
+
const geminiDir = import_node_path6.default.join(import_node_os5.default.homedir(), ".gemini");
|
|
1646
|
+
const globalConfigPath = import_node_path6.default.join(geminiDir, "GEMINI.md");
|
|
1647
|
+
const templatePath = import_node_path6.default.join(getPackageRoot(), "templates", "global", "GEMINI.md");
|
|
1648
|
+
await import_promises5.default.mkdir(geminiDir, { recursive: true });
|
|
1649
|
+
const templateContent = await import_promises5.default.readFile(templatePath, "utf-8");
|
|
1605
1650
|
let existingContent = "";
|
|
1606
1651
|
let configExists = false;
|
|
1607
1652
|
try {
|
|
1608
|
-
existingContent = await
|
|
1653
|
+
existingContent = await import_promises5.default.readFile(globalConfigPath, "utf-8");
|
|
1609
1654
|
configExists = true;
|
|
1610
1655
|
} catch (error) {
|
|
1611
1656
|
if (isNotFoundError(error)) {
|
|
@@ -1615,7 +1660,7 @@ async function installGeminiGlobalConfig() {
|
|
|
1615
1660
|
}
|
|
1616
1661
|
}
|
|
1617
1662
|
if (!configExists) {
|
|
1618
|
-
await
|
|
1663
|
+
await import_promises5.default.writeFile(globalConfigPath, templateContent, "utf-8");
|
|
1619
1664
|
return { success: true, action: "created" };
|
|
1620
1665
|
}
|
|
1621
1666
|
const startMarker = "<!-- prjct:start - DO NOT REMOVE THIS MARKER -->";
|
|
@@ -1625,7 +1670,7 @@ async function installGeminiGlobalConfig() {
|
|
|
1625
1670
|
const updatedContent2 = `${existingContent}
|
|
1626
1671
|
|
|
1627
1672
|
${templateContent}`;
|
|
1628
|
-
await
|
|
1673
|
+
await import_promises5.default.writeFile(globalConfigPath, updatedContent2, "utf-8");
|
|
1629
1674
|
return { success: true, action: "appended" };
|
|
1630
1675
|
}
|
|
1631
1676
|
const beforeMarker = existingContent.substring(0, existingContent.indexOf(startMarker));
|
|
@@ -1637,7 +1682,7 @@ ${templateContent}`;
|
|
|
1637
1682
|
templateContent.indexOf(endMarker) + endMarker.length
|
|
1638
1683
|
);
|
|
1639
1684
|
const updatedContent = beforeMarker + prjctSection + afterMarker;
|
|
1640
|
-
await
|
|
1685
|
+
await import_promises5.default.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
1641
1686
|
return { success: true, action: "updated" };
|
|
1642
1687
|
} catch (error) {
|
|
1643
1688
|
logger_default.warn(`Gemini config warning: ${getErrorMessage(error)}`);
|
|
@@ -1647,18 +1692,18 @@ ${templateContent}`;
|
|
|
1647
1692
|
__name(installGeminiGlobalConfig, "installGeminiGlobalConfig");
|
|
1648
1693
|
async function installAntigravitySkill() {
|
|
1649
1694
|
try {
|
|
1650
|
-
const antigravitySkillsDir =
|
|
1651
|
-
const prjctSkillDir =
|
|
1652
|
-
const skillMdPath =
|
|
1653
|
-
const templatePath =
|
|
1654
|
-
await
|
|
1695
|
+
const antigravitySkillsDir = import_node_path6.default.join(import_node_os5.default.homedir(), ".gemini", "antigravity", "skills");
|
|
1696
|
+
const prjctSkillDir = import_node_path6.default.join(antigravitySkillsDir, "prjct");
|
|
1697
|
+
const skillMdPath = import_node_path6.default.join(prjctSkillDir, "SKILL.md");
|
|
1698
|
+
const templatePath = import_node_path6.default.join(getPackageRoot(), "templates", "antigravity", "SKILL.md");
|
|
1699
|
+
await import_promises5.default.mkdir(prjctSkillDir, { recursive: true });
|
|
1655
1700
|
const skillExists = await fileExists(skillMdPath);
|
|
1656
1701
|
if (!await fileExists(templatePath)) {
|
|
1657
1702
|
logger_default.warn("Antigravity SKILL.md template not found");
|
|
1658
1703
|
return { success: false, action: null };
|
|
1659
1704
|
}
|
|
1660
|
-
const templateContent = await
|
|
1661
|
-
await
|
|
1705
|
+
const templateContent = await import_promises5.default.readFile(templatePath, "utf-8");
|
|
1706
|
+
await import_promises5.default.writeFile(skillMdPath, templateContent, "utf-8");
|
|
1662
1707
|
return { success: true, action: skillExists ? "updated" : "created" };
|
|
1663
1708
|
} catch (error) {
|
|
1664
1709
|
logger_default.warn(`Antigravity skill warning: ${getErrorMessage(error)}`);
|
|
@@ -1679,24 +1724,24 @@ async function installCursorProject(projectRoot) {
|
|
|
1679
1724
|
gitignoreUpdated: false
|
|
1680
1725
|
};
|
|
1681
1726
|
try {
|
|
1682
|
-
const cursorDir =
|
|
1683
|
-
const rulesDir =
|
|
1684
|
-
const commandsDir =
|
|
1685
|
-
const routerMdcDest =
|
|
1686
|
-
const routerMdcSource =
|
|
1687
|
-
const cursorCommandsSource =
|
|
1688
|
-
await
|
|
1689
|
-
await
|
|
1727
|
+
const cursorDir = import_node_path6.default.join(projectRoot, ".cursor");
|
|
1728
|
+
const rulesDir = import_node_path6.default.join(cursorDir, "rules");
|
|
1729
|
+
const commandsDir = import_node_path6.default.join(cursorDir, "commands");
|
|
1730
|
+
const routerMdcDest = import_node_path6.default.join(rulesDir, "prjct.mdc");
|
|
1731
|
+
const routerMdcSource = import_node_path6.default.join(getPackageRoot(), "templates", "cursor", "router.mdc");
|
|
1732
|
+
const cursorCommandsSource = import_node_path6.default.join(getPackageRoot(), "templates", "cursor", "commands");
|
|
1733
|
+
await import_promises5.default.mkdir(rulesDir, { recursive: true });
|
|
1734
|
+
await import_promises5.default.mkdir(commandsDir, { recursive: true });
|
|
1690
1735
|
if (await fileExists(routerMdcSource)) {
|
|
1691
|
-
await
|
|
1736
|
+
await import_promises5.default.copyFile(routerMdcSource, routerMdcDest);
|
|
1692
1737
|
result.rulesCreated = true;
|
|
1693
1738
|
}
|
|
1694
1739
|
if (await fileExists(cursorCommandsSource)) {
|
|
1695
|
-
const commandFiles = (await
|
|
1740
|
+
const commandFiles = (await import_promises5.default.readdir(cursorCommandsSource)).filter((f) => f.endsWith(".md"));
|
|
1696
1741
|
for (const file of commandFiles) {
|
|
1697
|
-
const src =
|
|
1698
|
-
const dest =
|
|
1699
|
-
await
|
|
1742
|
+
const src = import_node_path6.default.join(cursorCommandsSource, file);
|
|
1743
|
+
const dest = import_node_path6.default.join(commandsDir, file);
|
|
1744
|
+
await import_promises5.default.copyFile(src, dest);
|
|
1700
1745
|
}
|
|
1701
1746
|
result.commandsCreated = commandFiles.length > 0;
|
|
1702
1747
|
}
|
|
@@ -1711,7 +1756,7 @@ async function installCursorProject(projectRoot) {
|
|
|
1711
1756
|
__name(installCursorProject, "installCursorProject");
|
|
1712
1757
|
async function addCursorToGitignore(projectRoot) {
|
|
1713
1758
|
try {
|
|
1714
|
-
const gitignorePath =
|
|
1759
|
+
const gitignorePath = import_node_path6.default.join(projectRoot, ".gitignore");
|
|
1715
1760
|
const entriesToAdd = [
|
|
1716
1761
|
"# prjct Cursor routers (regenerated per-developer)",
|
|
1717
1762
|
".cursor/rules/prjct.mdc",
|
|
@@ -1726,7 +1771,7 @@ async function addCursorToGitignore(projectRoot) {
|
|
|
1726
1771
|
let content = "";
|
|
1727
1772
|
let configExists = false;
|
|
1728
1773
|
try {
|
|
1729
|
-
content = await
|
|
1774
|
+
content = await import_promises5.default.readFile(gitignorePath, "utf-8");
|
|
1730
1775
|
configExists = true;
|
|
1731
1776
|
} catch (error) {
|
|
1732
1777
|
if (!isNotFoundError(error)) {
|
|
@@ -1741,7 +1786,7 @@ async function addCursorToGitignore(projectRoot) {
|
|
|
1741
1786
|
${entriesToAdd.join("\n")}
|
|
1742
1787
|
` : `${entriesToAdd.join("\n")}
|
|
1743
1788
|
`;
|
|
1744
|
-
await
|
|
1789
|
+
await import_promises5.default.writeFile(gitignorePath, newContent, "utf-8");
|
|
1745
1790
|
return true;
|
|
1746
1791
|
} catch (error) {
|
|
1747
1792
|
logger_default.warn(`Gitignore update warning: ${getErrorMessage(error)}`);
|
|
@@ -1750,12 +1795,12 @@ ${entriesToAdd.join("\n")}
|
|
|
1750
1795
|
}
|
|
1751
1796
|
__name(addCursorToGitignore, "addCursorToGitignore");
|
|
1752
1797
|
async function hasCursorProject(projectRoot) {
|
|
1753
|
-
return await fileExists(
|
|
1798
|
+
return await fileExists(import_node_path6.default.join(projectRoot, ".cursor"));
|
|
1754
1799
|
}
|
|
1755
1800
|
__name(hasCursorProject, "hasCursorProject");
|
|
1756
1801
|
async function needsCursorRegeneration(projectRoot) {
|
|
1757
|
-
const cursorDir =
|
|
1758
|
-
const routerPath =
|
|
1802
|
+
const cursorDir = import_node_path6.default.join(projectRoot, ".cursor");
|
|
1803
|
+
const routerPath = import_node_path6.default.join(cursorDir, "rules", "prjct.mdc");
|
|
1759
1804
|
return await fileExists(cursorDir) && !await fileExists(routerPath);
|
|
1760
1805
|
}
|
|
1761
1806
|
__name(needsCursorRegeneration, "needsCursorRegeneration");
|
|
@@ -1767,31 +1812,31 @@ async function installWindsurfProject(projectRoot) {
|
|
|
1767
1812
|
gitignoreUpdated: false
|
|
1768
1813
|
};
|
|
1769
1814
|
try {
|
|
1770
|
-
const windsurfDir =
|
|
1771
|
-
const rulesDir =
|
|
1772
|
-
const workflowsDir =
|
|
1773
|
-
const routerDest =
|
|
1774
|
-
const routerSource =
|
|
1775
|
-
const windsurfWorkflowsSource =
|
|
1815
|
+
const windsurfDir = import_node_path6.default.join(projectRoot, ".windsurf");
|
|
1816
|
+
const rulesDir = import_node_path6.default.join(windsurfDir, "rules");
|
|
1817
|
+
const workflowsDir = import_node_path6.default.join(windsurfDir, "workflows");
|
|
1818
|
+
const routerDest = import_node_path6.default.join(rulesDir, "prjct.md");
|
|
1819
|
+
const routerSource = import_node_path6.default.join(getPackageRoot(), "templates", "windsurf", "router.md");
|
|
1820
|
+
const windsurfWorkflowsSource = import_node_path6.default.join(
|
|
1776
1821
|
getPackageRoot(),
|
|
1777
1822
|
"templates",
|
|
1778
1823
|
"windsurf",
|
|
1779
1824
|
"workflows"
|
|
1780
1825
|
);
|
|
1781
|
-
await
|
|
1782
|
-
await
|
|
1826
|
+
await import_promises5.default.mkdir(rulesDir, { recursive: true });
|
|
1827
|
+
await import_promises5.default.mkdir(workflowsDir, { recursive: true });
|
|
1783
1828
|
if (await fileExists(routerSource)) {
|
|
1784
|
-
await
|
|
1829
|
+
await import_promises5.default.copyFile(routerSource, routerDest);
|
|
1785
1830
|
result.rulesCreated = true;
|
|
1786
1831
|
}
|
|
1787
1832
|
if (await fileExists(windsurfWorkflowsSource)) {
|
|
1788
|
-
const workflowFiles = (await
|
|
1833
|
+
const workflowFiles = (await import_promises5.default.readdir(windsurfWorkflowsSource)).filter(
|
|
1789
1834
|
(f) => f.endsWith(".md")
|
|
1790
1835
|
);
|
|
1791
1836
|
for (const file of workflowFiles) {
|
|
1792
|
-
const src =
|
|
1793
|
-
const dest =
|
|
1794
|
-
await
|
|
1837
|
+
const src = import_node_path6.default.join(windsurfWorkflowsSource, file);
|
|
1838
|
+
const dest = import_node_path6.default.join(workflowsDir, file);
|
|
1839
|
+
await import_promises5.default.copyFile(src, dest);
|
|
1795
1840
|
}
|
|
1796
1841
|
result.workflowsCreated = workflowFiles.length > 0;
|
|
1797
1842
|
}
|
|
@@ -1806,7 +1851,7 @@ async function installWindsurfProject(projectRoot) {
|
|
|
1806
1851
|
__name(installWindsurfProject, "installWindsurfProject");
|
|
1807
1852
|
async function addWindsurfToGitignore(projectRoot) {
|
|
1808
1853
|
try {
|
|
1809
|
-
const gitignorePath =
|
|
1854
|
+
const gitignorePath = import_node_path6.default.join(projectRoot, ".gitignore");
|
|
1810
1855
|
const entriesToAdd = [
|
|
1811
1856
|
"# prjct Windsurf routers (regenerated per-developer)",
|
|
1812
1857
|
".windsurf/rules/prjct.md",
|
|
@@ -1821,7 +1866,7 @@ async function addWindsurfToGitignore(projectRoot) {
|
|
|
1821
1866
|
let content = "";
|
|
1822
1867
|
let configExists = false;
|
|
1823
1868
|
try {
|
|
1824
|
-
content = await
|
|
1869
|
+
content = await import_promises5.default.readFile(gitignorePath, "utf-8");
|
|
1825
1870
|
configExists = true;
|
|
1826
1871
|
} catch (error) {
|
|
1827
1872
|
if (!isNotFoundError(error)) {
|
|
@@ -1836,7 +1881,7 @@ async function addWindsurfToGitignore(projectRoot) {
|
|
|
1836
1881
|
${entriesToAdd.join("\n")}
|
|
1837
1882
|
` : `${entriesToAdd.join("\n")}
|
|
1838
1883
|
`;
|
|
1839
|
-
await
|
|
1884
|
+
await import_promises5.default.writeFile(gitignorePath, newContent, "utf-8");
|
|
1840
1885
|
return true;
|
|
1841
1886
|
} catch (error) {
|
|
1842
1887
|
logger_default.warn(`Gitignore update warning: ${getErrorMessage(error)}`);
|
|
@@ -1845,34 +1890,34 @@ ${entriesToAdd.join("\n")}
|
|
|
1845
1890
|
}
|
|
1846
1891
|
__name(addWindsurfToGitignore, "addWindsurfToGitignore");
|
|
1847
1892
|
async function hasWindsurfProject(projectRoot) {
|
|
1848
|
-
return await fileExists(
|
|
1893
|
+
return await fileExists(import_node_path6.default.join(projectRoot, ".windsurf"));
|
|
1849
1894
|
}
|
|
1850
1895
|
__name(hasWindsurfProject, "hasWindsurfProject");
|
|
1851
1896
|
async function needsWindsurfRegeneration(projectRoot) {
|
|
1852
|
-
const windsurfDir =
|
|
1853
|
-
const routerPath =
|
|
1897
|
+
const windsurfDir = import_node_path6.default.join(projectRoot, ".windsurf");
|
|
1898
|
+
const routerPath = import_node_path6.default.join(windsurfDir, "rules", "prjct.md");
|
|
1854
1899
|
return await fileExists(windsurfDir) && !await fileExists(routerPath);
|
|
1855
1900
|
}
|
|
1856
1901
|
__name(needsWindsurfRegeneration, "needsWindsurfRegeneration");
|
|
1857
1902
|
async function migrateProjectsCliVersion() {
|
|
1858
1903
|
try {
|
|
1859
|
-
const projectsDir =
|
|
1904
|
+
const projectsDir = import_node_path6.default.join(import_node_os5.default.homedir(), ".prjct-cli", "projects");
|
|
1860
1905
|
if (!await fileExists(projectsDir)) {
|
|
1861
1906
|
return;
|
|
1862
1907
|
}
|
|
1863
|
-
const projectDirs = (await
|
|
1908
|
+
const projectDirs = (await import_promises5.default.readdir(projectsDir, { withFileTypes: true })).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
1864
1909
|
let migrated = 0;
|
|
1865
1910
|
for (const projectId of projectDirs) {
|
|
1866
|
-
const projectJsonPath =
|
|
1911
|
+
const projectJsonPath = import_node_path6.default.join(projectsDir, projectId, "project.json");
|
|
1867
1912
|
if (!await fileExists(projectJsonPath)) {
|
|
1868
1913
|
continue;
|
|
1869
1914
|
}
|
|
1870
1915
|
try {
|
|
1871
|
-
const content = await
|
|
1916
|
+
const content = await import_promises5.default.readFile(projectJsonPath, "utf8");
|
|
1872
1917
|
const project = JSON.parse(content);
|
|
1873
1918
|
if (project.cliVersion !== VERSION) {
|
|
1874
1919
|
project.cliVersion = VERSION;
|
|
1875
|
-
await
|
|
1920
|
+
await import_promises5.default.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
|
|
1876
1921
|
migrated++;
|
|
1877
1922
|
}
|
|
1878
1923
|
} catch (error) {
|
|
@@ -1895,7 +1940,7 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
|
|
|
1895
1940
|
let settings = {};
|
|
1896
1941
|
if (await fileExists(settingsPath)) {
|
|
1897
1942
|
try {
|
|
1898
|
-
settings = JSON.parse(await
|
|
1943
|
+
settings = JSON.parse(await import_promises5.default.readFile(settingsPath, "utf8"));
|
|
1899
1944
|
} catch (error) {
|
|
1900
1945
|
if (!(error instanceof SyntaxError)) {
|
|
1901
1946
|
throw error;
|
|
@@ -1903,43 +1948,43 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
|
|
|
1903
1948
|
}
|
|
1904
1949
|
}
|
|
1905
1950
|
settings.statusLine = { type: "command", command: statusLinePath };
|
|
1906
|
-
await
|
|
1951
|
+
await import_promises5.default.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
1907
1952
|
}
|
|
1908
1953
|
__name(ensureStatusLineSettings, "ensureStatusLineSettings");
|
|
1909
1954
|
async function installStatusLine() {
|
|
1910
1955
|
try {
|
|
1911
|
-
const claudeDir =
|
|
1912
|
-
const settingsPath =
|
|
1913
|
-
const claudeStatusLinePath =
|
|
1914
|
-
const prjctStatusLineDir =
|
|
1915
|
-
const prjctStatusLinePath =
|
|
1916
|
-
const prjctThemesDir =
|
|
1917
|
-
const prjctLibDir =
|
|
1918
|
-
const prjctComponentsDir =
|
|
1919
|
-
const prjctConfigPath =
|
|
1920
|
-
const assetsDir =
|
|
1921
|
-
const sourceScript =
|
|
1922
|
-
const sourceThemeDir =
|
|
1923
|
-
const sourceLibDir =
|
|
1924
|
-
const sourceComponentsDir =
|
|
1925
|
-
const sourceConfigPath =
|
|
1956
|
+
const claudeDir = import_node_path6.default.join(import_node_os5.default.homedir(), ".claude");
|
|
1957
|
+
const settingsPath = import_node_path6.default.join(claudeDir, "settings.json");
|
|
1958
|
+
const claudeStatusLinePath = import_node_path6.default.join(claudeDir, "prjct-statusline.sh");
|
|
1959
|
+
const prjctStatusLineDir = import_node_path6.default.join(import_node_os5.default.homedir(), ".prjct-cli", "statusline");
|
|
1960
|
+
const prjctStatusLinePath = import_node_path6.default.join(prjctStatusLineDir, "statusline.sh");
|
|
1961
|
+
const prjctThemesDir = import_node_path6.default.join(prjctStatusLineDir, "themes");
|
|
1962
|
+
const prjctLibDir = import_node_path6.default.join(prjctStatusLineDir, "lib");
|
|
1963
|
+
const prjctComponentsDir = import_node_path6.default.join(prjctStatusLineDir, "components");
|
|
1964
|
+
const prjctConfigPath = import_node_path6.default.join(prjctStatusLineDir, "config.json");
|
|
1965
|
+
const assetsDir = import_node_path6.default.join(getPackageRoot(), "assets", "statusline");
|
|
1966
|
+
const sourceScript = import_node_path6.default.join(assetsDir, "statusline.sh");
|
|
1967
|
+
const sourceThemeDir = import_node_path6.default.join(assetsDir, "themes");
|
|
1968
|
+
const sourceLibDir = import_node_path6.default.join(assetsDir, "lib");
|
|
1969
|
+
const sourceComponentsDir = import_node_path6.default.join(assetsDir, "components");
|
|
1970
|
+
const sourceConfigPath = import_node_path6.default.join(assetsDir, "default-config.json");
|
|
1926
1971
|
if (!await fileExists(claudeDir)) {
|
|
1927
|
-
await
|
|
1972
|
+
await import_promises5.default.mkdir(claudeDir, { recursive: true });
|
|
1928
1973
|
}
|
|
1929
1974
|
if (!await fileExists(prjctStatusLineDir)) {
|
|
1930
|
-
await
|
|
1975
|
+
await import_promises5.default.mkdir(prjctStatusLineDir, { recursive: true });
|
|
1931
1976
|
}
|
|
1932
1977
|
if (!await fileExists(prjctThemesDir)) {
|
|
1933
|
-
await
|
|
1978
|
+
await import_promises5.default.mkdir(prjctThemesDir, { recursive: true });
|
|
1934
1979
|
}
|
|
1935
1980
|
if (!await fileExists(prjctLibDir)) {
|
|
1936
|
-
await
|
|
1981
|
+
await import_promises5.default.mkdir(prjctLibDir, { recursive: true });
|
|
1937
1982
|
}
|
|
1938
1983
|
if (!await fileExists(prjctComponentsDir)) {
|
|
1939
|
-
await
|
|
1984
|
+
await import_promises5.default.mkdir(prjctComponentsDir, { recursive: true });
|
|
1940
1985
|
}
|
|
1941
1986
|
if (await fileExists(prjctStatusLinePath)) {
|
|
1942
|
-
const existingContent = await
|
|
1987
|
+
const existingContent = await import_promises5.default.readFile(prjctStatusLinePath, "utf8");
|
|
1943
1988
|
if (existingContent.includes("CLI_VERSION=")) {
|
|
1944
1989
|
const versionMatch = existingContent.match(/CLI_VERSION="([^"]*)"/);
|
|
1945
1990
|
if (versionMatch && versionMatch[1] !== VERSION) {
|
|
@@ -1947,7 +1992,7 @@ async function installStatusLine() {
|
|
|
1947
1992
|
/CLI_VERSION="[^"]*"/,
|
|
1948
1993
|
`CLI_VERSION="${VERSION}"`
|
|
1949
1994
|
);
|
|
1950
|
-
await
|
|
1995
|
+
await import_promises5.default.writeFile(prjctStatusLinePath, updatedContent, { mode: 493 });
|
|
1951
1996
|
}
|
|
1952
1997
|
await installStatusLineModules(sourceLibDir, prjctLibDir);
|
|
1953
1998
|
await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
|
|
@@ -1957,21 +2002,21 @@ async function installStatusLine() {
|
|
|
1957
2002
|
}
|
|
1958
2003
|
}
|
|
1959
2004
|
if (await fileExists(sourceScript)) {
|
|
1960
|
-
let scriptContent = await
|
|
2005
|
+
let scriptContent = await import_promises5.default.readFile(sourceScript, "utf8");
|
|
1961
2006
|
scriptContent = scriptContent.replace(/CLI_VERSION="[^"]*"/, `CLI_VERSION="${VERSION}"`);
|
|
1962
|
-
await
|
|
2007
|
+
await import_promises5.default.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
|
|
1963
2008
|
await installStatusLineModules(sourceLibDir, prjctLibDir);
|
|
1964
2009
|
await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
|
|
1965
2010
|
if (await fileExists(sourceThemeDir)) {
|
|
1966
|
-
const themes = await
|
|
2011
|
+
const themes = await import_promises5.default.readdir(sourceThemeDir);
|
|
1967
2012
|
for (const theme of themes) {
|
|
1968
|
-
const src =
|
|
1969
|
-
const dest =
|
|
1970
|
-
await
|
|
2013
|
+
const src = import_node_path6.default.join(sourceThemeDir, theme);
|
|
2014
|
+
const dest = import_node_path6.default.join(prjctThemesDir, theme);
|
|
2015
|
+
await import_promises5.default.copyFile(src, dest);
|
|
1971
2016
|
}
|
|
1972
2017
|
}
|
|
1973
2018
|
if (!await fileExists(prjctConfigPath) && await fileExists(sourceConfigPath)) {
|
|
1974
|
-
await
|
|
2019
|
+
await import_promises5.default.copyFile(sourceConfigPath, prjctConfigPath);
|
|
1975
2020
|
}
|
|
1976
2021
|
} else {
|
|
1977
2022
|
const scriptContent = `#!/bin/bash
|
|
@@ -2006,7 +2051,7 @@ if [ -f "$CONFIG" ]; then
|
|
|
2006
2051
|
fi
|
|
2007
2052
|
echo "prjct"
|
|
2008
2053
|
`;
|
|
2009
|
-
await
|
|
2054
|
+
await import_promises5.default.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
|
|
2010
2055
|
}
|
|
2011
2056
|
await ensureStatusLineSymlink(claudeStatusLinePath, prjctStatusLinePath);
|
|
2012
2057
|
await ensureStatusLineSettings(settingsPath, claudeStatusLinePath);
|
|
@@ -2019,10 +2064,10 @@ echo "prjct"
|
|
|
2019
2064
|
__name(installStatusLine, "installStatusLine");
|
|
2020
2065
|
async function installContext7MCP() {
|
|
2021
2066
|
try {
|
|
2022
|
-
const claudeDir =
|
|
2023
|
-
const mcpConfigPath =
|
|
2067
|
+
const claudeDir = import_node_path6.default.join(import_node_os5.default.homedir(), ".claude");
|
|
2068
|
+
const mcpConfigPath = import_node_path6.default.join(claudeDir, "mcp.json");
|
|
2024
2069
|
if (!await fileExists(claudeDir)) {
|
|
2025
|
-
await
|
|
2070
|
+
await import_promises5.default.mkdir(claudeDir, { recursive: true });
|
|
2026
2071
|
}
|
|
2027
2072
|
const context7Config = {
|
|
2028
2073
|
mcpServers: {
|
|
@@ -2033,16 +2078,16 @@ async function installContext7MCP() {
|
|
|
2033
2078
|
}
|
|
2034
2079
|
};
|
|
2035
2080
|
if (await fileExists(mcpConfigPath)) {
|
|
2036
|
-
const existingContent = await
|
|
2081
|
+
const existingContent = await import_promises5.default.readFile(mcpConfigPath, "utf-8");
|
|
2037
2082
|
const existingConfig = JSON.parse(existingContent);
|
|
2038
2083
|
if (existingConfig.mcpServers?.context7) {
|
|
2039
2084
|
return;
|
|
2040
2085
|
}
|
|
2041
2086
|
existingConfig.mcpServers = existingConfig.mcpServers || {};
|
|
2042
2087
|
existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
|
|
2043
|
-
await
|
|
2088
|
+
await import_promises5.default.writeFile(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
|
|
2044
2089
|
} else {
|
|
2045
|
-
await
|
|
2090
|
+
await import_promises5.default.writeFile(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
|
|
2046
2091
|
}
|
|
2047
2092
|
} catch (error) {
|
|
2048
2093
|
logger_default.warn(`Context7 MCP setup warning: ${getErrorMessage(error)}`);
|
|
@@ -2053,13 +2098,13 @@ async function installStatusLineModules(sourceDir, destDir) {
|
|
|
2053
2098
|
if (!await fileExists(sourceDir)) {
|
|
2054
2099
|
return;
|
|
2055
2100
|
}
|
|
2056
|
-
const files = await
|
|
2101
|
+
const files = await import_promises5.default.readdir(sourceDir);
|
|
2057
2102
|
for (const file of files) {
|
|
2058
2103
|
if (file.endsWith(".sh")) {
|
|
2059
|
-
const src =
|
|
2060
|
-
const dest =
|
|
2061
|
-
await
|
|
2062
|
-
await
|
|
2104
|
+
const src = import_node_path6.default.join(sourceDir, file);
|
|
2105
|
+
const dest = import_node_path6.default.join(destDir, file);
|
|
2106
|
+
await import_promises5.default.copyFile(src, dest);
|
|
2107
|
+
await import_promises5.default.chmod(dest, 493);
|
|
2063
2108
|
}
|
|
2064
2109
|
}
|
|
2065
2110
|
}
|
|
@@ -2067,21 +2112,21 @@ __name(installStatusLineModules, "installStatusLineModules");
|
|
|
2067
2112
|
async function ensureStatusLineSymlink(linkPath, targetPath) {
|
|
2068
2113
|
try {
|
|
2069
2114
|
if (await fileExists(linkPath)) {
|
|
2070
|
-
const stats = await
|
|
2115
|
+
const stats = await import_promises5.default.lstat(linkPath);
|
|
2071
2116
|
if (stats.isSymbolicLink()) {
|
|
2072
|
-
const existingTarget = await
|
|
2117
|
+
const existingTarget = await import_promises5.default.readlink(linkPath);
|
|
2073
2118
|
if (existingTarget === targetPath) {
|
|
2074
2119
|
return;
|
|
2075
2120
|
}
|
|
2076
2121
|
}
|
|
2077
|
-
await
|
|
2122
|
+
await import_promises5.default.unlink(linkPath);
|
|
2078
2123
|
}
|
|
2079
|
-
await
|
|
2124
|
+
await import_promises5.default.symlink(targetPath, linkPath);
|
|
2080
2125
|
} catch (_error) {
|
|
2081
2126
|
try {
|
|
2082
2127
|
if (await fileExists(targetPath)) {
|
|
2083
|
-
await
|
|
2084
|
-
await
|
|
2128
|
+
await import_promises5.default.copyFile(targetPath, linkPath);
|
|
2129
|
+
await import_promises5.default.chmod(linkPath, 493);
|
|
2085
2130
|
}
|
|
2086
2131
|
} catch (copyError) {
|
|
2087
2132
|
if (!isNotFoundError(copyError)) {
|