prjct-cli 1.16.0 → 1.17.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 +41 -1
- package/core/__tests__/domain/bm25.test.ts +225 -0
- package/core/__tests__/domain/file-ranker.test.ts +169 -0
- package/core/__tests__/domain/git-cochange.test.ts +121 -0
- package/core/__tests__/domain/import-graph.test.ts +156 -0
- package/core/agentic/smart-context.ts +33 -2
- package/core/domain/bm25.ts +525 -0
- package/core/domain/file-ranker.ts +151 -0
- package/core/domain/git-cochange.ts +250 -0
- package/core/domain/import-graph.ts +315 -0
- package/core/services/sync-service.ts +17 -0
- package/dist/bin/prjct.mjs +890 -366
- package/package.json +1 -1
package/dist/bin/prjct.mjs
CHANGED
|
@@ -16,10 +16,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
16
16
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
17
17
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
18
18
|
});
|
|
19
|
-
var __glob = (map) => (
|
|
20
|
-
var fn = map[
|
|
19
|
+
var __glob = (map) => (path72) => {
|
|
20
|
+
var fn = map[path72];
|
|
21
21
|
if (fn) return fn();
|
|
22
|
-
throw new Error("Module not found in bundle: " +
|
|
22
|
+
throw new Error("Module not found in bundle: " + path72);
|
|
23
23
|
};
|
|
24
24
|
var __esm = (fn, res) => function __init() {
|
|
25
25
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -4051,7 +4051,7 @@ var init_cache = __esm({
|
|
|
4051
4051
|
import { Database } from "bun:sqlite";
|
|
4052
4052
|
import fs15 from "node:fs";
|
|
4053
4053
|
import path14 from "node:path";
|
|
4054
|
-
var migrations, PrjctDatabase, prjctDb;
|
|
4054
|
+
var migrations, PrjctDatabase, prjctDb, database_default;
|
|
4055
4055
|
var init_database = __esm({
|
|
4056
4056
|
"core/storage/database.ts"() {
|
|
4057
4057
|
"use strict";
|
|
@@ -4482,6 +4482,7 @@ var init_database = __esm({
|
|
|
4482
4482
|
}
|
|
4483
4483
|
};
|
|
4484
4484
|
prjctDb = new PrjctDatabase();
|
|
4485
|
+
database_default = prjctDb;
|
|
4485
4486
|
}
|
|
4486
4487
|
});
|
|
4487
4488
|
|
|
@@ -6575,11 +6576,11 @@ async function runSignaturesTool(args2, projectPath) {
|
|
|
6575
6576
|
}
|
|
6576
6577
|
};
|
|
6577
6578
|
}
|
|
6578
|
-
const
|
|
6579
|
-
const
|
|
6580
|
-
const fullPath =
|
|
6579
|
+
const fs60 = await import("node:fs/promises");
|
|
6580
|
+
const path72 = await import("node:path");
|
|
6581
|
+
const fullPath = path72.isAbsolute(filePath) ? filePath : path72.join(projectPath, filePath);
|
|
6581
6582
|
try {
|
|
6582
|
-
const stat = await
|
|
6583
|
+
const stat = await fs60.stat(fullPath);
|
|
6583
6584
|
if (stat.isDirectory()) {
|
|
6584
6585
|
const results = await extractDirectorySignatures(filePath, projectPath, {
|
|
6585
6586
|
recursive: args2.includes("--recursive") || args2.includes("-r")
|
|
@@ -6646,11 +6647,11 @@ async function runSummaryTool(args2, projectPath) {
|
|
|
6646
6647
|
}
|
|
6647
6648
|
};
|
|
6648
6649
|
}
|
|
6649
|
-
const
|
|
6650
|
-
const
|
|
6651
|
-
const fullPath =
|
|
6650
|
+
const fs60 = await import("node:fs/promises");
|
|
6651
|
+
const path72 = await import("node:path");
|
|
6652
|
+
const fullPath = path72.isAbsolute(targetPath) ? targetPath : path72.join(projectPath, targetPath);
|
|
6652
6653
|
try {
|
|
6653
|
-
const stat = await
|
|
6654
|
+
const stat = await fs60.stat(fullPath);
|
|
6654
6655
|
if (stat.isDirectory()) {
|
|
6655
6656
|
const results = await summarizeDirectory(targetPath, projectPath, {
|
|
6656
6657
|
recursive: args2.includes("--recursive") || args2.includes("-r")
|
|
@@ -21767,16 +21768,16 @@ var init_onboarding = __esm({
|
|
|
21767
21768
|
* Detect project type from file system
|
|
21768
21769
|
*/
|
|
21769
21770
|
async detectProjectType() {
|
|
21770
|
-
const
|
|
21771
|
-
const
|
|
21771
|
+
const fs60 = await import("node:fs/promises");
|
|
21772
|
+
const path72 = await import("node:path");
|
|
21772
21773
|
try {
|
|
21773
|
-
const files = await
|
|
21774
|
+
const files = await fs60.readdir(this.projectPath);
|
|
21774
21775
|
if (files.includes("turbo.json") || files.includes("lerna.json") || files.includes("nx.json")) {
|
|
21775
21776
|
return "monorepo";
|
|
21776
21777
|
}
|
|
21777
21778
|
if (files.includes("package.json")) {
|
|
21778
|
-
const pkgPath =
|
|
21779
|
-
const pkgContent = await
|
|
21779
|
+
const pkgPath = path72.join(this.projectPath, "package.json");
|
|
21780
|
+
const pkgContent = await fs60.readFile(pkgPath, "utf-8");
|
|
21780
21781
|
const pkg = JSON.parse(pkgContent);
|
|
21781
21782
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
21782
21783
|
if (pkg.bin) return "cli-tool";
|
|
@@ -21812,32 +21813,32 @@ var init_onboarding = __esm({
|
|
|
21812
21813
|
* Detect installed AI agents from config files
|
|
21813
21814
|
*/
|
|
21814
21815
|
async detectInstalledAgents() {
|
|
21815
|
-
const
|
|
21816
|
-
const
|
|
21816
|
+
const fs60 = await import("node:fs/promises");
|
|
21817
|
+
const path72 = await import("node:path");
|
|
21817
21818
|
const os22 = await import("node:os");
|
|
21818
21819
|
const agents = [];
|
|
21819
21820
|
try {
|
|
21820
|
-
await
|
|
21821
|
+
await fs60.access(path72.join(os22.homedir(), ".claude"));
|
|
21821
21822
|
agents.push("claude");
|
|
21822
21823
|
} catch {
|
|
21823
21824
|
}
|
|
21824
21825
|
try {
|
|
21825
|
-
await
|
|
21826
|
+
await fs60.access(path72.join(this.projectPath, ".cursorrules"));
|
|
21826
21827
|
agents.push("cursor");
|
|
21827
21828
|
} catch {
|
|
21828
21829
|
}
|
|
21829
21830
|
try {
|
|
21830
|
-
await
|
|
21831
|
+
await fs60.access(path72.join(this.projectPath, ".windsurfrules"));
|
|
21831
21832
|
agents.push("windsurf");
|
|
21832
21833
|
} catch {
|
|
21833
21834
|
}
|
|
21834
21835
|
try {
|
|
21835
|
-
await
|
|
21836
|
+
await fs60.access(path72.join(this.projectPath, ".github", "copilot-instructions.md"));
|
|
21836
21837
|
agents.push("copilot");
|
|
21837
21838
|
} catch {
|
|
21838
21839
|
}
|
|
21839
21840
|
try {
|
|
21840
|
-
await
|
|
21841
|
+
await fs60.access(path72.join(os22.homedir(), ".gemini"));
|
|
21841
21842
|
agents.push("gemini");
|
|
21842
21843
|
} catch {
|
|
21843
21844
|
}
|
|
@@ -21847,17 +21848,17 @@ var init_onboarding = __esm({
|
|
|
21847
21848
|
* Detect tech stack from project files
|
|
21848
21849
|
*/
|
|
21849
21850
|
async detectStack() {
|
|
21850
|
-
const
|
|
21851
|
-
const
|
|
21851
|
+
const fs60 = await import("node:fs/promises");
|
|
21852
|
+
const path72 = await import("node:path");
|
|
21852
21853
|
const stack = {
|
|
21853
21854
|
language: "Unknown",
|
|
21854
21855
|
technologies: []
|
|
21855
21856
|
};
|
|
21856
21857
|
try {
|
|
21857
|
-
const files = await
|
|
21858
|
+
const files = await fs60.readdir(this.projectPath);
|
|
21858
21859
|
if (files.includes("package.json")) {
|
|
21859
|
-
const pkgPath =
|
|
21860
|
-
const pkgContent = await
|
|
21860
|
+
const pkgPath = path72.join(this.projectPath, "package.json");
|
|
21861
|
+
const pkgContent = await fs60.readFile(pkgPath, "utf-8");
|
|
21861
21862
|
const pkg = JSON.parse(pkgContent);
|
|
21862
21863
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
21863
21864
|
stack.language = deps.typescript ? "TypeScript" : "JavaScript";
|
|
@@ -24082,8 +24083,8 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
|
24082
24083
|
const globalPath2 = path_manager_default.getGlobalProjectPath(projectId);
|
|
24083
24084
|
const specsPath2 = path45.join(globalPath2, "planning", "specs");
|
|
24084
24085
|
try {
|
|
24085
|
-
const
|
|
24086
|
-
const files = await
|
|
24086
|
+
const fs60 = await import("node:fs/promises");
|
|
24087
|
+
const files = await fs60.readdir(specsPath2);
|
|
24087
24088
|
const specs = files.filter((f) => f.endsWith(".md") && f !== ".gitkeep");
|
|
24088
24089
|
if (specs.length === 0) {
|
|
24089
24090
|
output_default.warn("no specs yet");
|
|
@@ -25010,9 +25011,518 @@ var init_ai_tools = __esm({
|
|
|
25010
25011
|
}
|
|
25011
25012
|
});
|
|
25012
25013
|
|
|
25013
|
-
// core/
|
|
25014
|
+
// core/domain/bm25.ts
|
|
25014
25015
|
import fs46 from "node:fs/promises";
|
|
25015
25016
|
import path49 from "node:path";
|
|
25017
|
+
function splitIdentifier(identifier) {
|
|
25018
|
+
return identifier.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[-_./]/g, " ").toLowerCase().split(/\s+/).filter((w) => w.length > 1);
|
|
25019
|
+
}
|
|
25020
|
+
function tokenizeFile(content, filePath) {
|
|
25021
|
+
const tokens = [];
|
|
25022
|
+
const pathParts = filePath.replace(/\.[^.]+$/, "").split(/[/\\]/).filter(Boolean);
|
|
25023
|
+
for (const part of pathParts) {
|
|
25024
|
+
tokens.push(...splitIdentifier(part));
|
|
25025
|
+
}
|
|
25026
|
+
const exportPatterns = [
|
|
25027
|
+
/export\s+(?:async\s+)?function\s+(\w+)/g,
|
|
25028
|
+
/export\s+class\s+(\w+)/g,
|
|
25029
|
+
/export\s+interface\s+(\w+)/g,
|
|
25030
|
+
/export\s+type\s+(\w+)/g,
|
|
25031
|
+
/export\s+(?:const|let|var)\s+(\w+)/g,
|
|
25032
|
+
/export\s+default\s+(?:class|function)\s+(\w+)/g
|
|
25033
|
+
];
|
|
25034
|
+
for (const pattern of exportPatterns) {
|
|
25035
|
+
let match;
|
|
25036
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
25037
|
+
if (match[1]) {
|
|
25038
|
+
tokens.push(...splitIdentifier(match[1]));
|
|
25039
|
+
}
|
|
25040
|
+
}
|
|
25041
|
+
}
|
|
25042
|
+
const declPatterns = [
|
|
25043
|
+
/(?:async\s+)?function\s+(\w+)/g,
|
|
25044
|
+
/class\s+(\w+)/g,
|
|
25045
|
+
/interface\s+(\w+)/g,
|
|
25046
|
+
/type\s+(\w+)\s*=/g
|
|
25047
|
+
];
|
|
25048
|
+
for (const pattern of declPatterns) {
|
|
25049
|
+
let match;
|
|
25050
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
25051
|
+
if (match[1]) {
|
|
25052
|
+
tokens.push(...splitIdentifier(match[1]));
|
|
25053
|
+
}
|
|
25054
|
+
}
|
|
25055
|
+
}
|
|
25056
|
+
const importPattern = /(?:from|import)\s+['"]([^'"]+)['"]/g;
|
|
25057
|
+
let importMatch;
|
|
25058
|
+
while ((importMatch = importPattern.exec(content)) !== null) {
|
|
25059
|
+
const source = importMatch[1];
|
|
25060
|
+
if (source.startsWith(".") || source.startsWith("@/")) {
|
|
25061
|
+
tokens.push(...splitIdentifier(source));
|
|
25062
|
+
} else {
|
|
25063
|
+
const pkgName = source.startsWith("@") ? source.split("/").slice(0, 2).join("/") : source.split("/")[0];
|
|
25064
|
+
tokens.push(...splitIdentifier(pkgName));
|
|
25065
|
+
}
|
|
25066
|
+
}
|
|
25067
|
+
const singleLineComments = /\/\/\s*(.+)/g;
|
|
25068
|
+
let commentMatch;
|
|
25069
|
+
while ((commentMatch = singleLineComments.exec(content)) !== null) {
|
|
25070
|
+
const words = commentMatch[1].toLowerCase().split(/\s+/).filter((w) => w.length > 2);
|
|
25071
|
+
tokens.push(...words);
|
|
25072
|
+
}
|
|
25073
|
+
const multiLineComments = /\/\*\*?([\s\S]*?)\*\//g;
|
|
25074
|
+
let multiMatch;
|
|
25075
|
+
while ((multiMatch = multiLineComments.exec(content)) !== null) {
|
|
25076
|
+
const words = multiMatch[1].replace(/@\w+/g, "").replace(/\*/g, "").toLowerCase().split(/\s+/).filter((w) => w.length > 2 && /^[a-z]+$/.test(w));
|
|
25077
|
+
tokens.push(...words);
|
|
25078
|
+
}
|
|
25079
|
+
return tokens.filter((t) => t.length > 1 && !STOP_WORDS.has(t) && /^[a-z][a-z0-9]*$/.test(t));
|
|
25080
|
+
}
|
|
25081
|
+
async function listFiles2(dir, projectPath) {
|
|
25082
|
+
const files = [];
|
|
25083
|
+
const entries = await fs46.readdir(dir, { withFileTypes: true });
|
|
25084
|
+
for (const entry of entries) {
|
|
25085
|
+
if (SKIP_DIRS.has(entry.name)) continue;
|
|
25086
|
+
const fullPath = path49.join(dir, entry.name);
|
|
25087
|
+
if (entry.isDirectory()) {
|
|
25088
|
+
files.push(...await listFiles2(fullPath, projectPath));
|
|
25089
|
+
} else if (entry.isFile()) {
|
|
25090
|
+
const ext = path49.extname(entry.name).toLowerCase();
|
|
25091
|
+
if (INDEXABLE_EXTENSIONS.has(ext)) {
|
|
25092
|
+
files.push(path49.relative(projectPath, fullPath));
|
|
25093
|
+
}
|
|
25094
|
+
}
|
|
25095
|
+
}
|
|
25096
|
+
return files;
|
|
25097
|
+
}
|
|
25098
|
+
async function buildIndex(projectPath) {
|
|
25099
|
+
const files = await listFiles2(projectPath, projectPath);
|
|
25100
|
+
const documents = {};
|
|
25101
|
+
const invertedIndex = {};
|
|
25102
|
+
let totalLength = 0;
|
|
25103
|
+
const BATCH_SIZE = 50;
|
|
25104
|
+
for (let i = 0; i < files.length; i += BATCH_SIZE) {
|
|
25105
|
+
const batch = files.slice(i, i + BATCH_SIZE);
|
|
25106
|
+
const results = await Promise.all(
|
|
25107
|
+
batch.map(async (filePath) => {
|
|
25108
|
+
try {
|
|
25109
|
+
const content = await fs46.readFile(path49.join(projectPath, filePath), "utf-8");
|
|
25110
|
+
const tokens = tokenizeFile(content, filePath);
|
|
25111
|
+
return { filePath, tokens };
|
|
25112
|
+
} catch {
|
|
25113
|
+
return { filePath, tokens: [] };
|
|
25114
|
+
}
|
|
25115
|
+
})
|
|
25116
|
+
);
|
|
25117
|
+
for (const { filePath, tokens } of results) {
|
|
25118
|
+
if (tokens.length === 0) continue;
|
|
25119
|
+
documents[filePath] = { tokens, length: tokens.length };
|
|
25120
|
+
totalLength += tokens.length;
|
|
25121
|
+
const tfMap = /* @__PURE__ */ new Map();
|
|
25122
|
+
for (const token of tokens) {
|
|
25123
|
+
tfMap.set(token, (tfMap.get(token) || 0) + 1);
|
|
25124
|
+
}
|
|
25125
|
+
for (const [token, tf] of tfMap) {
|
|
25126
|
+
if (!invertedIndex[token]) {
|
|
25127
|
+
invertedIndex[token] = [];
|
|
25128
|
+
}
|
|
25129
|
+
invertedIndex[token].push({ path: filePath, tf });
|
|
25130
|
+
}
|
|
25131
|
+
}
|
|
25132
|
+
}
|
|
25133
|
+
const totalDocs = Object.keys(documents).length;
|
|
25134
|
+
return {
|
|
25135
|
+
documents,
|
|
25136
|
+
invertedIndex,
|
|
25137
|
+
avgDocLength: totalDocs > 0 ? totalLength / totalDocs : 0,
|
|
25138
|
+
totalDocs,
|
|
25139
|
+
builtAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
25140
|
+
};
|
|
25141
|
+
}
|
|
25142
|
+
function saveIndex(projectId, index) {
|
|
25143
|
+
const storable = {
|
|
25144
|
+
invertedIndex: index.invertedIndex,
|
|
25145
|
+
avgDocLength: index.avgDocLength,
|
|
25146
|
+
totalDocs: index.totalDocs,
|
|
25147
|
+
builtAt: index.builtAt,
|
|
25148
|
+
// Store document lengths (needed for scoring) but not full token lists
|
|
25149
|
+
docLengths: Object.fromEntries(Object.entries(index.documents).map(([p, d]) => [p, d.length]))
|
|
25150
|
+
};
|
|
25151
|
+
database_default.setDoc(projectId, INDEX_KEY, storable);
|
|
25152
|
+
}
|
|
25153
|
+
async function indexProject(projectPath, projectId) {
|
|
25154
|
+
const index = await buildIndex(projectPath);
|
|
25155
|
+
saveIndex(projectId, index);
|
|
25156
|
+
return index;
|
|
25157
|
+
}
|
|
25158
|
+
var INDEXABLE_EXTENSIONS, STOP_WORDS, SKIP_DIRS, INDEX_KEY;
|
|
25159
|
+
var init_bm25 = __esm({
|
|
25160
|
+
"core/domain/bm25.ts"() {
|
|
25161
|
+
"use strict";
|
|
25162
|
+
init_database();
|
|
25163
|
+
INDEXABLE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
25164
|
+
".ts",
|
|
25165
|
+
".tsx",
|
|
25166
|
+
".js",
|
|
25167
|
+
".jsx",
|
|
25168
|
+
".mjs",
|
|
25169
|
+
".cjs",
|
|
25170
|
+
".py",
|
|
25171
|
+
".go",
|
|
25172
|
+
".rs",
|
|
25173
|
+
".java",
|
|
25174
|
+
".cs",
|
|
25175
|
+
".rb",
|
|
25176
|
+
".php",
|
|
25177
|
+
".vue",
|
|
25178
|
+
".svelte"
|
|
25179
|
+
]);
|
|
25180
|
+
STOP_WORDS = /* @__PURE__ */ new Set([
|
|
25181
|
+
"the",
|
|
25182
|
+
"a",
|
|
25183
|
+
"an",
|
|
25184
|
+
"is",
|
|
25185
|
+
"are",
|
|
25186
|
+
"was",
|
|
25187
|
+
"were",
|
|
25188
|
+
"be",
|
|
25189
|
+
"been",
|
|
25190
|
+
"being",
|
|
25191
|
+
"have",
|
|
25192
|
+
"has",
|
|
25193
|
+
"had",
|
|
25194
|
+
"do",
|
|
25195
|
+
"does",
|
|
25196
|
+
"did",
|
|
25197
|
+
"will",
|
|
25198
|
+
"would",
|
|
25199
|
+
"could",
|
|
25200
|
+
"should",
|
|
25201
|
+
"may",
|
|
25202
|
+
"might",
|
|
25203
|
+
"shall",
|
|
25204
|
+
"can",
|
|
25205
|
+
"of",
|
|
25206
|
+
"in",
|
|
25207
|
+
"to",
|
|
25208
|
+
"for",
|
|
25209
|
+
"with",
|
|
25210
|
+
"on",
|
|
25211
|
+
"at",
|
|
25212
|
+
"from",
|
|
25213
|
+
"by",
|
|
25214
|
+
"as",
|
|
25215
|
+
"or",
|
|
25216
|
+
"and",
|
|
25217
|
+
"but",
|
|
25218
|
+
"if",
|
|
25219
|
+
"not",
|
|
25220
|
+
"no",
|
|
25221
|
+
"so",
|
|
25222
|
+
"up",
|
|
25223
|
+
"out",
|
|
25224
|
+
"this",
|
|
25225
|
+
"that",
|
|
25226
|
+
"it",
|
|
25227
|
+
"its",
|
|
25228
|
+
"all",
|
|
25229
|
+
"any",
|
|
25230
|
+
// Code noise
|
|
25231
|
+
"import",
|
|
25232
|
+
"export",
|
|
25233
|
+
"default",
|
|
25234
|
+
"const",
|
|
25235
|
+
"let",
|
|
25236
|
+
"var",
|
|
25237
|
+
"function",
|
|
25238
|
+
"class",
|
|
25239
|
+
"interface",
|
|
25240
|
+
"type",
|
|
25241
|
+
"return",
|
|
25242
|
+
"new",
|
|
25243
|
+
"true",
|
|
25244
|
+
"false",
|
|
25245
|
+
"null",
|
|
25246
|
+
"undefined",
|
|
25247
|
+
"void",
|
|
25248
|
+
"async",
|
|
25249
|
+
"await",
|
|
25250
|
+
"static",
|
|
25251
|
+
"public",
|
|
25252
|
+
"private",
|
|
25253
|
+
"protected",
|
|
25254
|
+
"readonly",
|
|
25255
|
+
"string",
|
|
25256
|
+
"number",
|
|
25257
|
+
"boolean",
|
|
25258
|
+
"object",
|
|
25259
|
+
"array"
|
|
25260
|
+
]);
|
|
25261
|
+
SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
25262
|
+
"node_modules",
|
|
25263
|
+
".git",
|
|
25264
|
+
"dist",
|
|
25265
|
+
"build",
|
|
25266
|
+
"out",
|
|
25267
|
+
".next",
|
|
25268
|
+
"coverage",
|
|
25269
|
+
".cache",
|
|
25270
|
+
".turbo",
|
|
25271
|
+
".vercel",
|
|
25272
|
+
"__pycache__",
|
|
25273
|
+
"vendor",
|
|
25274
|
+
"target"
|
|
25275
|
+
]);
|
|
25276
|
+
__name(splitIdentifier, "splitIdentifier");
|
|
25277
|
+
__name(tokenizeFile, "tokenizeFile");
|
|
25278
|
+
__name(listFiles2, "listFiles");
|
|
25279
|
+
__name(buildIndex, "buildIndex");
|
|
25280
|
+
INDEX_KEY = "bm25-index";
|
|
25281
|
+
__name(saveIndex, "saveIndex");
|
|
25282
|
+
__name(indexProject, "indexProject");
|
|
25283
|
+
}
|
|
25284
|
+
});
|
|
25285
|
+
|
|
25286
|
+
// core/domain/git-cochange.ts
|
|
25287
|
+
import { exec as execCallback7 } from "node:child_process";
|
|
25288
|
+
import { promisify as promisify15 } from "node:util";
|
|
25289
|
+
async function parseGitLog(projectPath, maxCommits = 100) {
|
|
25290
|
+
try {
|
|
25291
|
+
const { stdout } = await exec14(
|
|
25292
|
+
`git log --name-only --pretty=format:'---COMMIT---' -${maxCommits}`,
|
|
25293
|
+
{ cwd: projectPath, maxBuffer: 10 * 1024 * 1024 }
|
|
25294
|
+
);
|
|
25295
|
+
const commits = [];
|
|
25296
|
+
let currentFiles = null;
|
|
25297
|
+
for (const line of stdout.split("\n")) {
|
|
25298
|
+
const trimmed = line.trim();
|
|
25299
|
+
if (trimmed === "---COMMIT---") {
|
|
25300
|
+
if (currentFiles && currentFiles.size > 0 && currentFiles.size <= MAX_FILES_PER_COMMIT) {
|
|
25301
|
+
commits.push(currentFiles);
|
|
25302
|
+
}
|
|
25303
|
+
currentFiles = /* @__PURE__ */ new Set();
|
|
25304
|
+
} else if (trimmed && currentFiles) {
|
|
25305
|
+
if (isSourceFile(trimmed)) {
|
|
25306
|
+
currentFiles.add(trimmed);
|
|
25307
|
+
}
|
|
25308
|
+
}
|
|
25309
|
+
}
|
|
25310
|
+
if (currentFiles && currentFiles.size > 0 && currentFiles.size <= MAX_FILES_PER_COMMIT) {
|
|
25311
|
+
commits.push(currentFiles);
|
|
25312
|
+
}
|
|
25313
|
+
return commits;
|
|
25314
|
+
} catch {
|
|
25315
|
+
return [];
|
|
25316
|
+
}
|
|
25317
|
+
}
|
|
25318
|
+
function isSourceFile(filePath) {
|
|
25319
|
+
const sourceExtensions = /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|cs|rb|php|vue|svelte)$/i;
|
|
25320
|
+
return sourceExtensions.test(filePath) && !filePath.includes("node_modules/");
|
|
25321
|
+
}
|
|
25322
|
+
async function buildMatrix(projectPath, maxCommits = 100) {
|
|
25323
|
+
const commitSets = await parseGitLog(projectPath, maxCommits);
|
|
25324
|
+
const fileCommitCount = /* @__PURE__ */ new Map();
|
|
25325
|
+
const pairCount = /* @__PURE__ */ new Map();
|
|
25326
|
+
for (const files of commitSets) {
|
|
25327
|
+
const fileArray = Array.from(files);
|
|
25328
|
+
for (const file of fileArray) {
|
|
25329
|
+
fileCommitCount.set(file, (fileCommitCount.get(file) || 0) + 1);
|
|
25330
|
+
}
|
|
25331
|
+
for (let i = 0; i < fileArray.length; i++) {
|
|
25332
|
+
for (let j = i + 1; j < fileArray.length; j++) {
|
|
25333
|
+
const key = pairKey(fileArray[i], fileArray[j]);
|
|
25334
|
+
pairCount.set(key, (pairCount.get(key) || 0) + 1);
|
|
25335
|
+
}
|
|
25336
|
+
}
|
|
25337
|
+
}
|
|
25338
|
+
const matrix = {};
|
|
25339
|
+
for (const [key, count] of pairCount) {
|
|
25340
|
+
const [fileA, fileB] = key.split("\0");
|
|
25341
|
+
const countA = fileCommitCount.get(fileA) || 0;
|
|
25342
|
+
const countB = fileCommitCount.get(fileB) || 0;
|
|
25343
|
+
if (countA < MIN_FILE_OCCURRENCES || countB < MIN_FILE_OCCURRENCES) continue;
|
|
25344
|
+
const unionCount = countA + countB - count;
|
|
25345
|
+
const similarity = unionCount > 0 ? count / unionCount : 0;
|
|
25346
|
+
if (similarity < MIN_SIMILARITY) continue;
|
|
25347
|
+
if (!matrix[fileA]) matrix[fileA] = {};
|
|
25348
|
+
if (!matrix[fileB]) matrix[fileB] = {};
|
|
25349
|
+
matrix[fileA][fileB] = similarity;
|
|
25350
|
+
matrix[fileB][fileA] = similarity;
|
|
25351
|
+
}
|
|
25352
|
+
return {
|
|
25353
|
+
matrix,
|
|
25354
|
+
commitsAnalyzed: commitSets.length,
|
|
25355
|
+
filesAnalyzed: fileCommitCount.size,
|
|
25356
|
+
builtAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
25357
|
+
};
|
|
25358
|
+
}
|
|
25359
|
+
function pairKey(a, b) {
|
|
25360
|
+
return a < b ? `${a}\0${b}` : `${b}\0${a}`;
|
|
25361
|
+
}
|
|
25362
|
+
function saveMatrix(projectId, index) {
|
|
25363
|
+
database_default.setDoc(projectId, INDEX_KEY2, index);
|
|
25364
|
+
}
|
|
25365
|
+
async function indexCoChanges(projectPath, projectId, maxCommits = 100) {
|
|
25366
|
+
const index = await buildMatrix(projectPath, maxCommits);
|
|
25367
|
+
saveMatrix(projectId, index);
|
|
25368
|
+
return index;
|
|
25369
|
+
}
|
|
25370
|
+
var exec14, MIN_SIMILARITY, MIN_FILE_OCCURRENCES, MAX_FILES_PER_COMMIT, INDEX_KEY2;
|
|
25371
|
+
var init_git_cochange = __esm({
|
|
25372
|
+
"core/domain/git-cochange.ts"() {
|
|
25373
|
+
"use strict";
|
|
25374
|
+
init_database();
|
|
25375
|
+
exec14 = promisify15(execCallback7);
|
|
25376
|
+
MIN_SIMILARITY = 0.1;
|
|
25377
|
+
MIN_FILE_OCCURRENCES = 2;
|
|
25378
|
+
MAX_FILES_PER_COMMIT = 30;
|
|
25379
|
+
__name(parseGitLog, "parseGitLog");
|
|
25380
|
+
__name(isSourceFile, "isSourceFile");
|
|
25381
|
+
__name(buildMatrix, "buildMatrix");
|
|
25382
|
+
__name(pairKey, "pairKey");
|
|
25383
|
+
INDEX_KEY2 = "cochange-index";
|
|
25384
|
+
__name(saveMatrix, "saveMatrix");
|
|
25385
|
+
__name(indexCoChanges, "indexCoChanges");
|
|
25386
|
+
}
|
|
25387
|
+
});
|
|
25388
|
+
|
|
25389
|
+
// core/domain/import-graph.ts
|
|
25390
|
+
import fs47 from "node:fs/promises";
|
|
25391
|
+
import path50 from "node:path";
|
|
25392
|
+
function extractImportSources(content) {
|
|
25393
|
+
const sources = [];
|
|
25394
|
+
let match;
|
|
25395
|
+
const regex = new RegExp(IMPORT_REGEX.source, "g");
|
|
25396
|
+
while ((match = regex.exec(content)) !== null) {
|
|
25397
|
+
const source = match[1];
|
|
25398
|
+
if (source.startsWith(".") || source.startsWith("@/")) {
|
|
25399
|
+
sources.push(source);
|
|
25400
|
+
}
|
|
25401
|
+
}
|
|
25402
|
+
return sources;
|
|
25403
|
+
}
|
|
25404
|
+
async function resolveImport2(source, fromFile, projectPath) {
|
|
25405
|
+
let basePath;
|
|
25406
|
+
if (source.startsWith("@/")) {
|
|
25407
|
+
basePath = path50.join(projectPath, "src", source.slice(2));
|
|
25408
|
+
} else {
|
|
25409
|
+
const fromDir = path50.dirname(path50.join(projectPath, fromFile));
|
|
25410
|
+
basePath = path50.resolve(fromDir, source);
|
|
25411
|
+
}
|
|
25412
|
+
for (const ext of RESOLVE_EXTENSIONS) {
|
|
25413
|
+
const fullPath = basePath + ext;
|
|
25414
|
+
try {
|
|
25415
|
+
const stat = await fs47.stat(fullPath);
|
|
25416
|
+
if (stat.isFile()) {
|
|
25417
|
+
return path50.relative(projectPath, fullPath);
|
|
25418
|
+
}
|
|
25419
|
+
} catch {
|
|
25420
|
+
}
|
|
25421
|
+
}
|
|
25422
|
+
return null;
|
|
25423
|
+
}
|
|
25424
|
+
async function listFiles3(dir, projectPath) {
|
|
25425
|
+
const files = [];
|
|
25426
|
+
const entries = await fs47.readdir(dir, { withFileTypes: true });
|
|
25427
|
+
for (const entry of entries) {
|
|
25428
|
+
if (SKIP_DIRS2.has(entry.name)) continue;
|
|
25429
|
+
const fullPath = path50.join(dir, entry.name);
|
|
25430
|
+
if (entry.isDirectory()) {
|
|
25431
|
+
files.push(...await listFiles3(fullPath, projectPath));
|
|
25432
|
+
} else if (entry.isFile()) {
|
|
25433
|
+
const ext = path50.extname(entry.name).toLowerCase();
|
|
25434
|
+
if (INDEXABLE_EXTENSIONS2.has(ext)) {
|
|
25435
|
+
files.push(path50.relative(projectPath, fullPath));
|
|
25436
|
+
}
|
|
25437
|
+
}
|
|
25438
|
+
}
|
|
25439
|
+
return files;
|
|
25440
|
+
}
|
|
25441
|
+
async function buildGraph(projectPath) {
|
|
25442
|
+
const files = await listFiles3(projectPath, projectPath);
|
|
25443
|
+
const forward = {};
|
|
25444
|
+
const reverse = {};
|
|
25445
|
+
let edgeCount = 0;
|
|
25446
|
+
const BATCH_SIZE = 50;
|
|
25447
|
+
for (let i = 0; i < files.length; i += BATCH_SIZE) {
|
|
25448
|
+
const batch = files.slice(i, i + BATCH_SIZE);
|
|
25449
|
+
const results = await Promise.all(
|
|
25450
|
+
batch.map(async (filePath) => {
|
|
25451
|
+
try {
|
|
25452
|
+
const content = await fs47.readFile(path50.join(projectPath, filePath), "utf-8");
|
|
25453
|
+
const sources = extractImportSources(content);
|
|
25454
|
+
const resolved = [];
|
|
25455
|
+
for (const source of sources) {
|
|
25456
|
+
const target = await resolveImport2(source, filePath, projectPath);
|
|
25457
|
+
if (target && target !== filePath) {
|
|
25458
|
+
resolved.push(target);
|
|
25459
|
+
}
|
|
25460
|
+
}
|
|
25461
|
+
return { filePath, imports: resolved };
|
|
25462
|
+
} catch {
|
|
25463
|
+
return { filePath, imports: [] };
|
|
25464
|
+
}
|
|
25465
|
+
})
|
|
25466
|
+
);
|
|
25467
|
+
for (const { filePath, imports } of results) {
|
|
25468
|
+
if (imports.length === 0) continue;
|
|
25469
|
+
forward[filePath] = imports;
|
|
25470
|
+
edgeCount += imports.length;
|
|
25471
|
+
for (const target of imports) {
|
|
25472
|
+
if (!reverse[target]) reverse[target] = [];
|
|
25473
|
+
reverse[target].push(filePath);
|
|
25474
|
+
}
|
|
25475
|
+
}
|
|
25476
|
+
}
|
|
25477
|
+
return {
|
|
25478
|
+
forward,
|
|
25479
|
+
reverse,
|
|
25480
|
+
fileCount: files.length,
|
|
25481
|
+
edgeCount,
|
|
25482
|
+
builtAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
25483
|
+
};
|
|
25484
|
+
}
|
|
25485
|
+
function saveGraph(projectId, graph) {
|
|
25486
|
+
database_default.setDoc(projectId, INDEX_KEY3, graph);
|
|
25487
|
+
}
|
|
25488
|
+
async function indexImports(projectPath, projectId) {
|
|
25489
|
+
const graph = await buildGraph(projectPath);
|
|
25490
|
+
saveGraph(projectId, graph);
|
|
25491
|
+
return graph;
|
|
25492
|
+
}
|
|
25493
|
+
var INDEXABLE_EXTENSIONS2, SKIP_DIRS2, RESOLVE_EXTENSIONS, IMPORT_REGEX, INDEX_KEY3;
|
|
25494
|
+
var init_import_graph = __esm({
|
|
25495
|
+
"core/domain/import-graph.ts"() {
|
|
25496
|
+
"use strict";
|
|
25497
|
+
init_database();
|
|
25498
|
+
INDEXABLE_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
25499
|
+
SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
25500
|
+
"node_modules",
|
|
25501
|
+
".git",
|
|
25502
|
+
"dist",
|
|
25503
|
+
"build",
|
|
25504
|
+
"out",
|
|
25505
|
+
".next",
|
|
25506
|
+
"coverage",
|
|
25507
|
+
".cache",
|
|
25508
|
+
".turbo",
|
|
25509
|
+
".vercel"
|
|
25510
|
+
]);
|
|
25511
|
+
RESOLVE_EXTENSIONS = ["", ".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.js"];
|
|
25512
|
+
IMPORT_REGEX = /(?:import|from)\s+['"]([^'"]+)['"]/g;
|
|
25513
|
+
__name(extractImportSources, "extractImportSources");
|
|
25514
|
+
__name(resolveImport2, "resolveImport");
|
|
25515
|
+
__name(listFiles3, "listFiles");
|
|
25516
|
+
__name(buildGraph, "buildGraph");
|
|
25517
|
+
INDEX_KEY3 = "import-graph";
|
|
25518
|
+
__name(saveGraph, "saveGraph");
|
|
25519
|
+
__name(indexImports, "indexImports");
|
|
25520
|
+
}
|
|
25521
|
+
});
|
|
25522
|
+
|
|
25523
|
+
// core/services/context-generator.ts
|
|
25524
|
+
import fs48 from "node:fs/promises";
|
|
25525
|
+
import path51 from "node:path";
|
|
25016
25526
|
var ContextFileGenerator;
|
|
25017
25527
|
var init_context_generator = __esm({
|
|
25018
25528
|
"core/services/context-generator.ts"() {
|
|
@@ -25037,10 +25547,10 @@ var init_context_generator = __esm({
|
|
|
25037
25547
|
async writeWithPreservation(filePath, content) {
|
|
25038
25548
|
let finalContent = content;
|
|
25039
25549
|
try {
|
|
25040
|
-
const existingContent = await
|
|
25550
|
+
const existingContent = await fs48.readFile(filePath, "utf-8");
|
|
25041
25551
|
const validation = validatePreserveBlocks(existingContent);
|
|
25042
25552
|
if (!validation.valid) {
|
|
25043
|
-
const filename =
|
|
25553
|
+
const filename = path51.basename(filePath);
|
|
25044
25554
|
console.warn(`\u26A0\uFE0F ${filename} has invalid preserve blocks:`);
|
|
25045
25555
|
for (const error of validation.errors) {
|
|
25046
25556
|
console.warn(` ${error}`);
|
|
@@ -25049,13 +25559,13 @@ var init_context_generator = __esm({
|
|
|
25049
25559
|
finalContent = mergePreservedSections(content, existingContent);
|
|
25050
25560
|
} catch {
|
|
25051
25561
|
}
|
|
25052
|
-
await
|
|
25562
|
+
await fs48.writeFile(filePath, finalContent, "utf-8");
|
|
25053
25563
|
}
|
|
25054
25564
|
/**
|
|
25055
25565
|
* Generate all context files in parallel
|
|
25056
25566
|
*/
|
|
25057
25567
|
async generate(git, stats, commands, agents, sources) {
|
|
25058
|
-
const contextPath =
|
|
25568
|
+
const contextPath = path51.join(this.config.globalPath, "context");
|
|
25059
25569
|
await Promise.all([
|
|
25060
25570
|
this.generateClaudeMd(contextPath, git, stats, commands, agents, sources),
|
|
25061
25571
|
this.generateNowMd(contextPath),
|
|
@@ -25155,7 +25665,7 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
|
|
|
25155
25665
|
**Workflow**: ${workflowAgents.join(", ")}
|
|
25156
25666
|
**Domain**: ${domainAgents.join(", ") || "none"}
|
|
25157
25667
|
`;
|
|
25158
|
-
const claudePath =
|
|
25668
|
+
const claudePath = path51.join(contextPath, "CLAUDE.md");
|
|
25159
25669
|
await this.writeWithPreservation(claudePath, content);
|
|
25160
25670
|
}
|
|
25161
25671
|
/**
|
|
@@ -25164,8 +25674,8 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
|
|
|
25164
25674
|
async generateNowMd(contextPath) {
|
|
25165
25675
|
let currentTask = null;
|
|
25166
25676
|
try {
|
|
25167
|
-
const statePath =
|
|
25168
|
-
const state = JSON.parse(await
|
|
25677
|
+
const statePath = path51.join(this.config.globalPath, "storage", "state.json");
|
|
25678
|
+
const state = JSON.parse(await fs48.readFile(statePath, "utf-8"));
|
|
25169
25679
|
currentTask = state.currentTask;
|
|
25170
25680
|
} catch {
|
|
25171
25681
|
}
|
|
@@ -25181,7 +25691,7 @@ _No active task_
|
|
|
25181
25691
|
|
|
25182
25692
|
Use \`p. task "description"\` to start working.
|
|
25183
25693
|
`;
|
|
25184
|
-
await this.writeWithPreservation(
|
|
25694
|
+
await this.writeWithPreservation(path51.join(contextPath, "now.md"), content);
|
|
25185
25695
|
}
|
|
25186
25696
|
/**
|
|
25187
25697
|
* Generate next.md - task queue
|
|
@@ -25189,15 +25699,15 @@ Use \`p. task "description"\` to start working.
|
|
|
25189
25699
|
async generateNextMd(contextPath) {
|
|
25190
25700
|
let queue = { tasks: [] };
|
|
25191
25701
|
try {
|
|
25192
|
-
const queuePath =
|
|
25193
|
-
queue = JSON.parse(await
|
|
25702
|
+
const queuePath = path51.join(this.config.globalPath, "storage", "queue.json");
|
|
25703
|
+
queue = JSON.parse(await fs48.readFile(queuePath, "utf-8"));
|
|
25194
25704
|
} catch {
|
|
25195
25705
|
}
|
|
25196
25706
|
const content = `# NEXT
|
|
25197
25707
|
|
|
25198
25708
|
${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ""}`).join("\n") : "_Empty queue_"}
|
|
25199
25709
|
`;
|
|
25200
|
-
await this.writeWithPreservation(
|
|
25710
|
+
await this.writeWithPreservation(path51.join(contextPath, "next.md"), content);
|
|
25201
25711
|
}
|
|
25202
25712
|
/**
|
|
25203
25713
|
* Generate ideas.md - captured ideas
|
|
@@ -25205,15 +25715,15 @@ ${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}
|
|
|
25205
25715
|
async generateIdeasMd(contextPath) {
|
|
25206
25716
|
let ideas = { ideas: [] };
|
|
25207
25717
|
try {
|
|
25208
|
-
const ideasPath =
|
|
25209
|
-
ideas = JSON.parse(await
|
|
25718
|
+
const ideasPath = path51.join(this.config.globalPath, "storage", "ideas.json");
|
|
25719
|
+
ideas = JSON.parse(await fs48.readFile(ideasPath, "utf-8"));
|
|
25210
25720
|
} catch {
|
|
25211
25721
|
}
|
|
25212
25722
|
const content = `# IDEAS
|
|
25213
25723
|
|
|
25214
25724
|
${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [${i.priority}]` : ""}`).join("\n") : "_No ideas captured yet_"}
|
|
25215
25725
|
`;
|
|
25216
|
-
await this.writeWithPreservation(
|
|
25726
|
+
await this.writeWithPreservation(path51.join(contextPath, "ideas.md"), content);
|
|
25217
25727
|
}
|
|
25218
25728
|
/**
|
|
25219
25729
|
* Generate shipped.md - completed features
|
|
@@ -25223,8 +25733,8 @@ ${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [
|
|
|
25223
25733
|
shipped: []
|
|
25224
25734
|
};
|
|
25225
25735
|
try {
|
|
25226
|
-
const shippedPath =
|
|
25227
|
-
shipped = JSON.parse(await
|
|
25736
|
+
const shippedPath = path51.join(this.config.globalPath, "storage", "shipped.json");
|
|
25737
|
+
shipped = JSON.parse(await fs48.readFile(shippedPath, "utf-8"));
|
|
25228
25738
|
} catch {
|
|
25229
25739
|
}
|
|
25230
25740
|
const content = `# SHIPPED \u{1F680}
|
|
@@ -25233,7 +25743,7 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
|
|
|
25233
25743
|
|
|
25234
25744
|
**Total shipped:** ${shipped.shipped.length}
|
|
25235
25745
|
`;
|
|
25236
|
-
await this.writeWithPreservation(
|
|
25746
|
+
await this.writeWithPreservation(path51.join(contextPath, "shipped.md"), content);
|
|
25237
25747
|
}
|
|
25238
25748
|
// ==========================================================================
|
|
25239
25749
|
// MONOREPO SUPPORT
|
|
@@ -25262,9 +25772,9 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
|
|
|
25262
25772
|
commands,
|
|
25263
25773
|
agents
|
|
25264
25774
|
);
|
|
25265
|
-
const claudePath =
|
|
25775
|
+
const claudePath = path51.join(pkg.path, "CLAUDE.md");
|
|
25266
25776
|
await this.writeWithPreservation(claudePath, content);
|
|
25267
|
-
generatedFiles.push(
|
|
25777
|
+
generatedFiles.push(path51.relative(this.config.projectPath, claudePath));
|
|
25268
25778
|
}
|
|
25269
25779
|
return generatedFiles;
|
|
25270
25780
|
}
|
|
@@ -25277,8 +25787,8 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
|
|
|
25277
25787
|
let pkgVersion = stats.version;
|
|
25278
25788
|
let pkgName = pkg.name;
|
|
25279
25789
|
try {
|
|
25280
|
-
const pkgJsonPath =
|
|
25281
|
-
const pkgJson = JSON.parse(await
|
|
25790
|
+
const pkgJsonPath = path51.join(pkg.path, "package.json");
|
|
25791
|
+
const pkgJson = JSON.parse(await fs48.readFile(pkgJsonPath, "utf-8"));
|
|
25282
25792
|
pkgVersion = pkgJson.version || stats.version;
|
|
25283
25793
|
pkgName = pkgJson.name || pkg.name;
|
|
25284
25794
|
} catch {
|
|
@@ -25343,8 +25853,8 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
|
|
|
25343
25853
|
});
|
|
25344
25854
|
|
|
25345
25855
|
// core/services/local-state-generator.ts
|
|
25346
|
-
import
|
|
25347
|
-
import
|
|
25856
|
+
import fs49 from "node:fs/promises";
|
|
25857
|
+
import path52 from "node:path";
|
|
25348
25858
|
var LOCAL_STATE_FILENAME, LocalStateGenerator, localStateGenerator;
|
|
25349
25859
|
var init_local_state_generator = __esm({
|
|
25350
25860
|
"core/services/local-state-generator.ts"() {
|
|
@@ -25359,17 +25869,17 @@ var init_local_state_generator = __esm({
|
|
|
25359
25869
|
* Generate .prjct-state.md in the project root
|
|
25360
25870
|
*/
|
|
25361
25871
|
async generate(projectPath, state) {
|
|
25362
|
-
const filePath =
|
|
25872
|
+
const filePath = path52.join(projectPath, LOCAL_STATE_FILENAME);
|
|
25363
25873
|
const content = this.toMarkdown(state);
|
|
25364
|
-
await
|
|
25874
|
+
await fs49.writeFile(filePath, content, "utf-8");
|
|
25365
25875
|
}
|
|
25366
25876
|
/**
|
|
25367
25877
|
* Remove local state file
|
|
25368
25878
|
*/
|
|
25369
25879
|
async remove(projectPath) {
|
|
25370
|
-
const filePath =
|
|
25880
|
+
const filePath = path52.join(projectPath, LOCAL_STATE_FILENAME);
|
|
25371
25881
|
try {
|
|
25372
|
-
await
|
|
25882
|
+
await fs49.unlink(filePath);
|
|
25373
25883
|
} catch (error) {
|
|
25374
25884
|
if (!isNotFoundError(error)) throw error;
|
|
25375
25885
|
}
|
|
@@ -25378,9 +25888,9 @@ var init_local_state_generator = __esm({
|
|
|
25378
25888
|
* Check if local state file exists
|
|
25379
25889
|
*/
|
|
25380
25890
|
async exists(projectPath) {
|
|
25381
|
-
const filePath =
|
|
25891
|
+
const filePath = path52.join(projectPath, LOCAL_STATE_FILENAME);
|
|
25382
25892
|
try {
|
|
25383
|
-
await
|
|
25893
|
+
await fs49.access(filePath);
|
|
25384
25894
|
return true;
|
|
25385
25895
|
} catch {
|
|
25386
25896
|
return false;
|
|
@@ -25459,11 +25969,11 @@ var init_local_state_generator = __esm({
|
|
|
25459
25969
|
});
|
|
25460
25970
|
|
|
25461
25971
|
// core/services/skill-lock.ts
|
|
25462
|
-
import
|
|
25972
|
+
import fs50 from "node:fs/promises";
|
|
25463
25973
|
import os14 from "node:os";
|
|
25464
|
-
import
|
|
25974
|
+
import path53 from "node:path";
|
|
25465
25975
|
function getLockFilePath() {
|
|
25466
|
-
return
|
|
25976
|
+
return path53.join(os14.homedir(), ".prjct-cli", "skills", LOCK_FILE_NAME);
|
|
25467
25977
|
}
|
|
25468
25978
|
function createEmptyLockFile() {
|
|
25469
25979
|
return {
|
|
@@ -25474,7 +25984,7 @@ function createEmptyLockFile() {
|
|
|
25474
25984
|
}
|
|
25475
25985
|
async function read() {
|
|
25476
25986
|
try {
|
|
25477
|
-
const content = await
|
|
25987
|
+
const content = await fs50.readFile(getLockFilePath(), "utf-8");
|
|
25478
25988
|
return JSON.parse(content);
|
|
25479
25989
|
} catch {
|
|
25480
25990
|
return createEmptyLockFile();
|
|
@@ -25482,9 +25992,9 @@ async function read() {
|
|
|
25482
25992
|
}
|
|
25483
25993
|
async function write(lockFile) {
|
|
25484
25994
|
const lockPath = getLockFilePath();
|
|
25485
|
-
await
|
|
25995
|
+
await fs50.mkdir(path53.dirname(lockPath), { recursive: true });
|
|
25486
25996
|
lockFile.generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
25487
|
-
await
|
|
25997
|
+
await fs50.writeFile(lockPath, JSON.stringify(lockFile, null, 2), "utf-8");
|
|
25488
25998
|
}
|
|
25489
25999
|
async function addEntry(entry) {
|
|
25490
26000
|
const lockFile = await read();
|
|
@@ -25536,15 +26046,15 @@ var init_skill_lock = __esm({
|
|
|
25536
26046
|
});
|
|
25537
26047
|
|
|
25538
26048
|
// core/services/skill-installer.ts
|
|
25539
|
-
import { exec as
|
|
25540
|
-
import
|
|
26049
|
+
import { exec as execCallback8 } from "node:child_process";
|
|
26050
|
+
import fs51 from "node:fs/promises";
|
|
25541
26051
|
import os15 from "node:os";
|
|
25542
|
-
import
|
|
25543
|
-
import { promisify as
|
|
26052
|
+
import path54 from "node:path";
|
|
26053
|
+
import { promisify as promisify16 } from "node:util";
|
|
25544
26054
|
import { glob } from "glob";
|
|
25545
26055
|
function parseSource(source) {
|
|
25546
26056
|
if (source.startsWith("./") || source.startsWith("/") || source.startsWith("~")) {
|
|
25547
|
-
const resolvedPath = source.startsWith("~") ?
|
|
26057
|
+
const resolvedPath = source.startsWith("~") ? path54.join(os15.homedir(), source.slice(1)) : path54.resolve(source);
|
|
25548
26058
|
return {
|
|
25549
26059
|
type: "local",
|
|
25550
26060
|
localPath: resolvedPath,
|
|
@@ -25582,22 +26092,22 @@ function parseSource(source) {
|
|
|
25582
26092
|
async function discoverSkills(dir) {
|
|
25583
26093
|
const skills = [];
|
|
25584
26094
|
try {
|
|
25585
|
-
const rootSkill =
|
|
25586
|
-
await
|
|
25587
|
-
const dirName =
|
|
26095
|
+
const rootSkill = path54.join(dir, "SKILL.md");
|
|
26096
|
+
await fs51.access(rootSkill);
|
|
26097
|
+
const dirName = path54.basename(dir);
|
|
25588
26098
|
skills.push({ name: dirName, filePath: rootSkill });
|
|
25589
26099
|
} catch {
|
|
25590
26100
|
}
|
|
25591
26101
|
const subdirSkills = await glob("*/SKILL.md", { cwd: dir, absolute: true });
|
|
25592
26102
|
for (const filePath of subdirSkills) {
|
|
25593
|
-
const name =
|
|
26103
|
+
const name = path54.basename(path54.dirname(filePath));
|
|
25594
26104
|
if (!skills.some((s) => s.name === name)) {
|
|
25595
26105
|
skills.push({ name, filePath });
|
|
25596
26106
|
}
|
|
25597
26107
|
}
|
|
25598
26108
|
const nestedSkills = await glob("skills/*/SKILL.md", { cwd: dir, absolute: true });
|
|
25599
26109
|
for (const filePath of nestedSkills) {
|
|
25600
|
-
const name =
|
|
26110
|
+
const name = path54.basename(path54.dirname(filePath));
|
|
25601
26111
|
if (!skills.some((s) => s.name === name)) {
|
|
25602
26112
|
skills.push({ name, filePath });
|
|
25603
26113
|
}
|
|
@@ -25633,16 +26143,16 @@ ${prjctBlock.join("\n")}
|
|
|
25633
26143
|
${content}`;
|
|
25634
26144
|
}
|
|
25635
26145
|
function getInstallDir() {
|
|
25636
|
-
return
|
|
26146
|
+
return path54.join(os15.homedir(), ".claude", "skills");
|
|
25637
26147
|
}
|
|
25638
26148
|
async function installSkillFile(sourcePath, name, source, sha) {
|
|
25639
26149
|
const installDir = getInstallDir();
|
|
25640
|
-
const targetDir =
|
|
25641
|
-
const targetPath =
|
|
25642
|
-
const content = await
|
|
26150
|
+
const targetDir = path54.join(installDir, name);
|
|
26151
|
+
const targetPath = path54.join(targetDir, "SKILL.md");
|
|
26152
|
+
const content = await fs51.readFile(sourcePath, "utf-8");
|
|
25643
26153
|
const enrichedContent = injectSourceMetadata(content, source, sha);
|
|
25644
|
-
await
|
|
25645
|
-
await
|
|
26154
|
+
await fs51.mkdir(targetDir, { recursive: true });
|
|
26155
|
+
await fs51.writeFile(targetPath, enrichedContent, "utf-8");
|
|
25646
26156
|
return {
|
|
25647
26157
|
name,
|
|
25648
26158
|
filePath: targetPath,
|
|
@@ -25659,13 +26169,13 @@ async function installFromGitHub(source) {
|
|
|
25659
26169
|
);
|
|
25660
26170
|
return result;
|
|
25661
26171
|
}
|
|
25662
|
-
const tmpDir =
|
|
26172
|
+
const tmpDir = path54.join(os15.tmpdir(), `prjct-skill-${Date.now()}`);
|
|
25663
26173
|
try {
|
|
25664
26174
|
const cloneUrl = `https://github.com/${source.owner}/${source.repo}.git`;
|
|
25665
|
-
await
|
|
26175
|
+
await exec15(`git clone --depth 1 ${cloneUrl} ${tmpDir}`, { timeout: getTimeout("GIT_CLONE") });
|
|
25666
26176
|
let sha;
|
|
25667
26177
|
try {
|
|
25668
|
-
const { stdout } = await
|
|
26178
|
+
const { stdout } = await exec15("git rev-parse HEAD", {
|
|
25669
26179
|
cwd: tmpDir,
|
|
25670
26180
|
timeout: getTimeout("TOOL_CHECK")
|
|
25671
26181
|
});
|
|
@@ -25703,7 +26213,7 @@ async function installFromGitHub(source) {
|
|
|
25703
26213
|
}
|
|
25704
26214
|
} finally {
|
|
25705
26215
|
try {
|
|
25706
|
-
await
|
|
26216
|
+
await fs51.rm(tmpDir, { recursive: true, force: true });
|
|
25707
26217
|
} catch {
|
|
25708
26218
|
}
|
|
25709
26219
|
}
|
|
@@ -25713,14 +26223,14 @@ async function installFromLocal(source) {
|
|
|
25713
26223
|
const result = { installed: [], skipped: [], errors: [] };
|
|
25714
26224
|
const localPath = source.localPath;
|
|
25715
26225
|
try {
|
|
25716
|
-
await
|
|
26226
|
+
await fs51.access(localPath);
|
|
25717
26227
|
} catch {
|
|
25718
26228
|
result.errors.push(`Local path not found: ${localPath}`);
|
|
25719
26229
|
return result;
|
|
25720
26230
|
}
|
|
25721
|
-
const stat = await
|
|
26231
|
+
const stat = await fs51.stat(localPath);
|
|
25722
26232
|
if (stat.isFile()) {
|
|
25723
|
-
const name =
|
|
26233
|
+
const name = path54.basename(path54.dirname(localPath));
|
|
25724
26234
|
try {
|
|
25725
26235
|
const installed = await installSkillFile(localPath, name, source);
|
|
25726
26236
|
const lockEntry = {
|
|
@@ -25760,14 +26270,14 @@ async function installFromLocal(source) {
|
|
|
25760
26270
|
}
|
|
25761
26271
|
async function remove(name) {
|
|
25762
26272
|
const installDir = getInstallDir();
|
|
25763
|
-
const subdirPath =
|
|
26273
|
+
const subdirPath = path54.join(installDir, name);
|
|
25764
26274
|
try {
|
|
25765
|
-
await
|
|
26275
|
+
await fs51.rm(subdirPath, { recursive: true, force: true });
|
|
25766
26276
|
} catch {
|
|
25767
26277
|
}
|
|
25768
|
-
const flatPath =
|
|
26278
|
+
const flatPath = path54.join(installDir, `${name}.md`);
|
|
25769
26279
|
try {
|
|
25770
|
-
await
|
|
26280
|
+
await fs51.rm(flatPath, { force: true });
|
|
25771
26281
|
} catch {
|
|
25772
26282
|
}
|
|
25773
26283
|
return skillLock.removeEntry(name);
|
|
@@ -25787,7 +26297,7 @@ async function install(sourceStr) {
|
|
|
25787
26297
|
};
|
|
25788
26298
|
}
|
|
25789
26299
|
}
|
|
25790
|
-
var
|
|
26300
|
+
var exec15, skillInstaller;
|
|
25791
26301
|
var init_skill_installer = __esm({
|
|
25792
26302
|
"core/services/skill-installer.ts"() {
|
|
25793
26303
|
"use strict";
|
|
@@ -25795,7 +26305,7 @@ var init_skill_installer = __esm({
|
|
|
25795
26305
|
init_fs();
|
|
25796
26306
|
init_dependency_validator();
|
|
25797
26307
|
init_skill_lock();
|
|
25798
|
-
|
|
26308
|
+
exec15 = promisify16(execCallback8);
|
|
25799
26309
|
__name(parseSource, "parseSource");
|
|
25800
26310
|
__name(discoverSkills, "discoverSkills");
|
|
25801
26311
|
__name(injectSourceMetadata, "injectSourceMetadata");
|
|
@@ -25815,8 +26325,8 @@ var init_skill_installer = __esm({
|
|
|
25815
26325
|
});
|
|
25816
26326
|
|
|
25817
26327
|
// core/services/stack-detector.ts
|
|
25818
|
-
import
|
|
25819
|
-
import
|
|
26328
|
+
import fs52 from "node:fs/promises";
|
|
26329
|
+
import path55 from "node:path";
|
|
25820
26330
|
var StackDetector;
|
|
25821
26331
|
var init_stack_detector = __esm({
|
|
25822
26332
|
"core/services/stack-detector.ts"() {
|
|
@@ -25975,8 +26485,8 @@ var init_stack_detector = __esm({
|
|
|
25975
26485
|
*/
|
|
25976
26486
|
async readPackageJson() {
|
|
25977
26487
|
try {
|
|
25978
|
-
const pkgPath =
|
|
25979
|
-
const content = await
|
|
26488
|
+
const pkgPath = path55.join(this.projectPath, "package.json");
|
|
26489
|
+
const content = await fs52.readFile(pkgPath, "utf-8");
|
|
25980
26490
|
return JSON.parse(content);
|
|
25981
26491
|
} catch {
|
|
25982
26492
|
return null;
|
|
@@ -25987,7 +26497,7 @@ var init_stack_detector = __esm({
|
|
|
25987
26497
|
*/
|
|
25988
26498
|
async fileExists(filename) {
|
|
25989
26499
|
try {
|
|
25990
|
-
await
|
|
26500
|
+
await fs52.access(path55.join(this.projectPath, filename));
|
|
25991
26501
|
return true;
|
|
25992
26502
|
} catch {
|
|
25993
26503
|
return false;
|
|
@@ -25998,16 +26508,16 @@ var init_stack_detector = __esm({
|
|
|
25998
26508
|
});
|
|
25999
26509
|
|
|
26000
26510
|
// core/services/sync-verifier.ts
|
|
26001
|
-
import { exec as
|
|
26002
|
-
import
|
|
26003
|
-
import
|
|
26004
|
-
import { promisify as
|
|
26511
|
+
import { exec as exec16 } from "node:child_process";
|
|
26512
|
+
import fs53 from "node:fs/promises";
|
|
26513
|
+
import path56 from "node:path";
|
|
26514
|
+
import { promisify as promisify17 } from "node:util";
|
|
26005
26515
|
var execAsync10, BUILTIN_CHECKS, SyncVerifier, syncVerifier;
|
|
26006
26516
|
var init_sync_verifier = __esm({
|
|
26007
26517
|
"core/services/sync-verifier.ts"() {
|
|
26008
26518
|
"use strict";
|
|
26009
26519
|
init_fs();
|
|
26010
|
-
execAsync10 =
|
|
26520
|
+
execAsync10 = promisify17(exec16);
|
|
26011
26521
|
BUILTIN_CHECKS = {
|
|
26012
26522
|
/**
|
|
26013
26523
|
* Verify all expected context files exist after sync
|
|
@@ -26017,9 +26527,9 @@ var init_sync_verifier = __esm({
|
|
|
26017
26527
|
const expected = ["context/CLAUDE.md"];
|
|
26018
26528
|
const missing = [];
|
|
26019
26529
|
for (const file of expected) {
|
|
26020
|
-
const filePath =
|
|
26530
|
+
const filePath = path56.join(globalPath, file);
|
|
26021
26531
|
try {
|
|
26022
|
-
await
|
|
26532
|
+
await fs53.access(filePath);
|
|
26023
26533
|
} catch {
|
|
26024
26534
|
missing.push(file);
|
|
26025
26535
|
}
|
|
@@ -26040,9 +26550,9 @@ var init_sync_verifier = __esm({
|
|
|
26040
26550
|
const jsonFiles = ["storage/state.json"];
|
|
26041
26551
|
const invalid = [];
|
|
26042
26552
|
for (const file of jsonFiles) {
|
|
26043
|
-
const filePath =
|
|
26553
|
+
const filePath = path56.join(globalPath, file);
|
|
26044
26554
|
try {
|
|
26045
|
-
const content = await
|
|
26555
|
+
const content = await fs53.readFile(filePath, "utf-8");
|
|
26046
26556
|
JSON.parse(content);
|
|
26047
26557
|
} catch (error) {
|
|
26048
26558
|
if (!isNotFoundError(error)) {
|
|
@@ -26063,7 +26573,7 @@ var init_sync_verifier = __esm({
|
|
|
26063
26573
|
*/
|
|
26064
26574
|
async noSensitiveData(globalPath) {
|
|
26065
26575
|
const start = Date.now();
|
|
26066
|
-
const contextDir =
|
|
26576
|
+
const contextDir = path56.join(globalPath, "context");
|
|
26067
26577
|
const patterns = [
|
|
26068
26578
|
/(?:api[_-]?key|apikey)\s*[:=]\s*['"][^'"]{10,}/i,
|
|
26069
26579
|
/(?:password|passwd|pwd)\s*[:=]\s*['"][^'"]{4,}/i,
|
|
@@ -26071,10 +26581,10 @@ var init_sync_verifier = __esm({
|
|
|
26071
26581
|
];
|
|
26072
26582
|
const violations = [];
|
|
26073
26583
|
try {
|
|
26074
|
-
const files = await
|
|
26584
|
+
const files = await fs53.readdir(contextDir);
|
|
26075
26585
|
for (const file of files) {
|
|
26076
26586
|
if (!file.endsWith(".md")) continue;
|
|
26077
|
-
const content = await
|
|
26587
|
+
const content = await fs53.readFile(path56.join(contextDir, file), "utf-8");
|
|
26078
26588
|
for (const pattern of patterns) {
|
|
26079
26589
|
if (pattern.test(content)) {
|
|
26080
26590
|
violations.push(`${file}: potential sensitive data detected`);
|
|
@@ -26194,16 +26704,19 @@ var init_sync_verifier = __esm({
|
|
|
26194
26704
|
});
|
|
26195
26705
|
|
|
26196
26706
|
// core/services/sync-service.ts
|
|
26197
|
-
import { exec as
|
|
26198
|
-
import
|
|
26707
|
+
import { exec as exec17 } from "node:child_process";
|
|
26708
|
+
import fs54 from "node:fs/promises";
|
|
26199
26709
|
import os16 from "node:os";
|
|
26200
|
-
import
|
|
26201
|
-
import { promisify as
|
|
26710
|
+
import path57 from "node:path";
|
|
26711
|
+
import { promisify as promisify18 } from "node:util";
|
|
26202
26712
|
var execAsync11, SyncService, syncService;
|
|
26203
26713
|
var init_sync_service = __esm({
|
|
26204
26714
|
"core/services/sync-service.ts"() {
|
|
26205
26715
|
"use strict";
|
|
26206
26716
|
init_ai_tools();
|
|
26717
|
+
init_bm25();
|
|
26718
|
+
init_git_cochange();
|
|
26719
|
+
init_import_graph();
|
|
26207
26720
|
init_errors();
|
|
26208
26721
|
init_command_installer();
|
|
26209
26722
|
init_config_manager();
|
|
@@ -26219,7 +26732,7 @@ var init_sync_service = __esm({
|
|
|
26219
26732
|
init_skill_installer();
|
|
26220
26733
|
init_stack_detector();
|
|
26221
26734
|
init_sync_verifier();
|
|
26222
|
-
execAsync11 =
|
|
26735
|
+
execAsync11 = promisify18(exec17);
|
|
26223
26736
|
SyncService = class {
|
|
26224
26737
|
static {
|
|
26225
26738
|
__name(this, "SyncService");
|
|
@@ -26281,6 +26794,17 @@ var init_sync_service = __esm({
|
|
|
26281
26794
|
this.detectCommands(),
|
|
26282
26795
|
this.detectStack()
|
|
26283
26796
|
]);
|
|
26797
|
+
try {
|
|
26798
|
+
await Promise.all([
|
|
26799
|
+
indexProject(this.projectPath, this.projectId),
|
|
26800
|
+
indexImports(this.projectPath, this.projectId),
|
|
26801
|
+
indexCoChanges(this.projectPath, this.projectId)
|
|
26802
|
+
]);
|
|
26803
|
+
} catch (error) {
|
|
26804
|
+
logger_default.debug("File ranking index build failed (non-critical)", {
|
|
26805
|
+
error: getErrorMessage(error)
|
|
26806
|
+
});
|
|
26807
|
+
}
|
|
26284
26808
|
const agents = await this.generateAgents(stack, stats);
|
|
26285
26809
|
const skills = this.configureSkills(agents);
|
|
26286
26810
|
const skillsInstalled = await this.autoInstallSkills(agents);
|
|
@@ -26377,7 +26901,7 @@ var init_sync_service = __esm({
|
|
|
26377
26901
|
async ensureDirectories() {
|
|
26378
26902
|
const dirs = ["storage", "context", "agents", "memory", "analysis", "config", "sync"];
|
|
26379
26903
|
await Promise.all(
|
|
26380
|
-
dirs.map((dir) =>
|
|
26904
|
+
dirs.map((dir) => fs54.mkdir(path57.join(this.globalPath, dir), { recursive: true }))
|
|
26381
26905
|
);
|
|
26382
26906
|
}
|
|
26383
26907
|
// ==========================================================================
|
|
@@ -26448,7 +26972,7 @@ var init_sync_service = __esm({
|
|
|
26448
26972
|
const stats = {
|
|
26449
26973
|
fileCount: 0,
|
|
26450
26974
|
version: "0.0.0",
|
|
26451
|
-
name:
|
|
26975
|
+
name: path57.basename(this.projectPath),
|
|
26452
26976
|
ecosystem: "unknown",
|
|
26453
26977
|
projectType: "simple",
|
|
26454
26978
|
languages: [],
|
|
@@ -26465,8 +26989,8 @@ var init_sync_service = __esm({
|
|
|
26465
26989
|
stats.fileCount = 0;
|
|
26466
26990
|
}
|
|
26467
26991
|
try {
|
|
26468
|
-
const pkgPath =
|
|
26469
|
-
const pkg = JSON.parse(await
|
|
26992
|
+
const pkgPath = path57.join(this.projectPath, "package.json");
|
|
26993
|
+
const pkg = JSON.parse(await fs54.readFile(pkgPath, "utf-8"));
|
|
26470
26994
|
stats.version = pkg.version || "0.0.0";
|
|
26471
26995
|
stats.name = pkg.name || stats.name;
|
|
26472
26996
|
stats.ecosystem = "JavaScript";
|
|
@@ -26611,12 +27135,12 @@ var init_sync_service = __esm({
|
|
|
26611
27135
|
// ==========================================================================
|
|
26612
27136
|
async generateAgents(stack, stats) {
|
|
26613
27137
|
const agents = [];
|
|
26614
|
-
const agentsPath =
|
|
27138
|
+
const agentsPath = path57.join(this.globalPath, "agents");
|
|
26615
27139
|
try {
|
|
26616
|
-
const files = await
|
|
27140
|
+
const files = await fs54.readdir(agentsPath);
|
|
26617
27141
|
for (const file of files) {
|
|
26618
27142
|
if (file.endsWith(".md")) {
|
|
26619
|
-
await
|
|
27143
|
+
await fs54.unlink(path57.join(agentsPath, file));
|
|
26620
27144
|
}
|
|
26621
27145
|
}
|
|
26622
27146
|
} catch (error) {
|
|
@@ -26665,7 +27189,7 @@ var init_sync_service = __esm({
|
|
|
26665
27189
|
let resolved = content;
|
|
26666
27190
|
for (const match of matches) {
|
|
26667
27191
|
const partialName = match[1];
|
|
26668
|
-
const partialPath =
|
|
27192
|
+
const partialPath = path57.join(
|
|
26669
27193
|
__dirname,
|
|
26670
27194
|
"..",
|
|
26671
27195
|
"..",
|
|
@@ -26674,7 +27198,7 @@ var init_sync_service = __esm({
|
|
|
26674
27198
|
`${partialName}.md`
|
|
26675
27199
|
);
|
|
26676
27200
|
try {
|
|
26677
|
-
const partialContent = await
|
|
27201
|
+
const partialContent = await fs54.readFile(partialPath, "utf-8");
|
|
26678
27202
|
resolved = resolved.replace(match[0], partialContent.trim());
|
|
26679
27203
|
} catch {
|
|
26680
27204
|
resolved = resolved.replace(match[0], `<!-- partial "${partialName}" not found -->`);
|
|
@@ -26685,7 +27209,7 @@ var init_sync_service = __esm({
|
|
|
26685
27209
|
async generateWorkflowAgent(name, agentsPath) {
|
|
26686
27210
|
let content = "";
|
|
26687
27211
|
try {
|
|
26688
|
-
const templatePath =
|
|
27212
|
+
const templatePath = path57.join(
|
|
26689
27213
|
__dirname,
|
|
26690
27214
|
"..",
|
|
26691
27215
|
"..",
|
|
@@ -26694,7 +27218,7 @@ var init_sync_service = __esm({
|
|
|
26694
27218
|
"workflow",
|
|
26695
27219
|
`${name}.md`
|
|
26696
27220
|
);
|
|
26697
|
-
content = await
|
|
27221
|
+
content = await fs54.readFile(templatePath, "utf-8");
|
|
26698
27222
|
content = await this.resolveTemplateIncludes(content);
|
|
26699
27223
|
} catch (error) {
|
|
26700
27224
|
logger_default.debug("Workflow agent template not found, generating minimal", {
|
|
@@ -26703,12 +27227,12 @@ var init_sync_service = __esm({
|
|
|
26703
27227
|
});
|
|
26704
27228
|
content = this.generateMinimalWorkflowAgent(name);
|
|
26705
27229
|
}
|
|
26706
|
-
await
|
|
27230
|
+
await fs54.writeFile(path57.join(agentsPath, `${name}.md`), content, "utf-8");
|
|
26707
27231
|
}
|
|
26708
27232
|
async generateDomainAgent(name, agentsPath, stats, stack) {
|
|
26709
27233
|
let content = "";
|
|
26710
27234
|
try {
|
|
26711
|
-
const templatePath =
|
|
27235
|
+
const templatePath = path57.join(
|
|
26712
27236
|
__dirname,
|
|
26713
27237
|
"..",
|
|
26714
27238
|
"..",
|
|
@@ -26717,7 +27241,7 @@ var init_sync_service = __esm({
|
|
|
26717
27241
|
"domain",
|
|
26718
27242
|
`${name}.md`
|
|
26719
27243
|
);
|
|
26720
|
-
content = await
|
|
27244
|
+
content = await fs54.readFile(templatePath, "utf-8");
|
|
26721
27245
|
content = await this.resolveTemplateIncludes(content);
|
|
26722
27246
|
content = content.replace("{projectName}", stats.name);
|
|
26723
27247
|
content = content.replace("{frameworks}", stack.frameworks.join(", ") || "None detected");
|
|
@@ -26729,7 +27253,7 @@ var init_sync_service = __esm({
|
|
|
26729
27253
|
});
|
|
26730
27254
|
content = this.generateMinimalDomainAgent(name, stats, stack);
|
|
26731
27255
|
}
|
|
26732
|
-
await
|
|
27256
|
+
await fs54.writeFile(path57.join(agentsPath, `${name}.md`), content, "utf-8");
|
|
26733
27257
|
}
|
|
26734
27258
|
generateMinimalWorkflowAgent(name) {
|
|
26735
27259
|
const descriptions = {
|
|
@@ -26797,8 +27321,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
26797
27321
|
})),
|
|
26798
27322
|
agentSkillMap: Object.fromEntries(skills.map((s) => [s.agent, s.skill]))
|
|
26799
27323
|
};
|
|
26800
|
-
|
|
26801
|
-
|
|
27324
|
+
fs54.writeFile(
|
|
27325
|
+
path57.join(this.globalPath, "config", "skills.json"),
|
|
26802
27326
|
JSON.stringify(skillsConfig, null, 2),
|
|
26803
27327
|
"utf-8"
|
|
26804
27328
|
).catch((error) => {
|
|
@@ -26816,7 +27340,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
26816
27340
|
async autoInstallSkills(agents) {
|
|
26817
27341
|
const results = [];
|
|
26818
27342
|
try {
|
|
26819
|
-
const mappingsPath =
|
|
27343
|
+
const mappingsPath = path57.join(
|
|
26820
27344
|
__dirname,
|
|
26821
27345
|
"..",
|
|
26822
27346
|
"..",
|
|
@@ -26824,7 +27348,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
26824
27348
|
"config",
|
|
26825
27349
|
"skill-mappings.json"
|
|
26826
27350
|
);
|
|
26827
|
-
const mappingsContent = await
|
|
27351
|
+
const mappingsContent = await fs54.readFile(mappingsPath, "utf-8");
|
|
26828
27352
|
const mappings = JSON.parse(mappingsContent);
|
|
26829
27353
|
const agentToSkillMap = mappings.agentToSkillMap || {};
|
|
26830
27354
|
const packagesToInstall = [];
|
|
@@ -26837,18 +27361,18 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
26837
27361
|
}
|
|
26838
27362
|
}
|
|
26839
27363
|
if (packagesToInstall.length === 0) return results;
|
|
26840
|
-
const skillsDir =
|
|
27364
|
+
const skillsDir = path57.join(os16.homedir(), ".claude", "skills");
|
|
26841
27365
|
for (const { pkg, agent } of packagesToInstall) {
|
|
26842
27366
|
const skillName = pkg.split("/").pop() || pkg;
|
|
26843
|
-
const subdirPath =
|
|
26844
|
-
const flatPath =
|
|
27367
|
+
const subdirPath = path57.join(skillsDir, skillName, "SKILL.md");
|
|
27368
|
+
const flatPath = path57.join(skillsDir, `${skillName}.md`);
|
|
26845
27369
|
let alreadyInstalled = false;
|
|
26846
27370
|
try {
|
|
26847
|
-
await
|
|
27371
|
+
await fs54.access(subdirPath);
|
|
26848
27372
|
alreadyInstalled = true;
|
|
26849
27373
|
} catch {
|
|
26850
27374
|
try {
|
|
26851
|
-
await
|
|
27375
|
+
await fs54.access(flatPath);
|
|
26852
27376
|
alreadyInstalled = true;
|
|
26853
27377
|
} catch {
|
|
26854
27378
|
}
|
|
@@ -26900,10 +27424,10 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
26900
27424
|
// PROJECT.JSON UPDATE
|
|
26901
27425
|
// ==========================================================================
|
|
26902
27426
|
async updateProjectJson(git, stats) {
|
|
26903
|
-
const projectJsonPath =
|
|
27427
|
+
const projectJsonPath = path57.join(this.globalPath, "project.json");
|
|
26904
27428
|
let existing = {};
|
|
26905
27429
|
try {
|
|
26906
|
-
existing = JSON.parse(await
|
|
27430
|
+
existing = JSON.parse(await fs54.readFile(projectJsonPath, "utf-8"));
|
|
26907
27431
|
} catch (error) {
|
|
26908
27432
|
logger_default.debug("No existing project.json", {
|
|
26909
27433
|
path: projectJsonPath,
|
|
@@ -26929,16 +27453,16 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
26929
27453
|
lastSyncCommit: git.recentCommits[0]?.hash || null,
|
|
26930
27454
|
lastSyncBranch: git.branch
|
|
26931
27455
|
};
|
|
26932
|
-
await
|
|
27456
|
+
await fs54.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
26933
27457
|
}
|
|
26934
27458
|
// ==========================================================================
|
|
26935
27459
|
// STATE.JSON UPDATE
|
|
26936
27460
|
// ==========================================================================
|
|
26937
27461
|
async updateStateJson(stats, stack) {
|
|
26938
|
-
const statePath =
|
|
27462
|
+
const statePath = path57.join(this.globalPath, "storage", "state.json");
|
|
26939
27463
|
let state = {};
|
|
26940
27464
|
try {
|
|
26941
|
-
state = JSON.parse(await
|
|
27465
|
+
state = JSON.parse(await fs54.readFile(statePath, "utf-8"));
|
|
26942
27466
|
} catch (error) {
|
|
26943
27467
|
logger_default.debug("No existing state.json", { path: statePath, error: getErrorMessage(error) });
|
|
26944
27468
|
}
|
|
@@ -26966,7 +27490,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
26966
27490
|
lastAction: "Synced project",
|
|
26967
27491
|
nextAction: 'Run `p. task "description"` to start working'
|
|
26968
27492
|
};
|
|
26969
|
-
await
|
|
27493
|
+
await fs54.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
|
|
26970
27494
|
try {
|
|
26971
27495
|
await localStateGenerator.generate(
|
|
26972
27496
|
this.projectPath,
|
|
@@ -26980,7 +27504,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
26980
27504
|
// MEMORY LOGGING
|
|
26981
27505
|
// ==========================================================================
|
|
26982
27506
|
async logToMemory(git, stats) {
|
|
26983
|
-
const memoryPath =
|
|
27507
|
+
const memoryPath = path57.join(this.globalPath, "memory", "events.jsonl");
|
|
26984
27508
|
const event = {
|
|
26985
27509
|
ts: getTimestamp(),
|
|
26986
27510
|
action: "sync",
|
|
@@ -26989,7 +27513,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
26989
27513
|
fileCount: stats.fileCount,
|
|
26990
27514
|
commitCount: git.commits
|
|
26991
27515
|
};
|
|
26992
|
-
await
|
|
27516
|
+
await fs54.appendFile(memoryPath, `${JSON.stringify(event)}
|
|
26993
27517
|
`, "utf-8");
|
|
26994
27518
|
}
|
|
26995
27519
|
// ==========================================================================
|
|
@@ -27009,8 +27533,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
27009
27533
|
let filteredChars = 0;
|
|
27010
27534
|
for (const file of contextFiles) {
|
|
27011
27535
|
try {
|
|
27012
|
-
const filePath =
|
|
27013
|
-
const content = await
|
|
27536
|
+
const filePath = path57.join(this.globalPath, file);
|
|
27537
|
+
const content = await fs54.readFile(filePath, "utf-8");
|
|
27014
27538
|
filteredChars += content.length;
|
|
27015
27539
|
} catch (error) {
|
|
27016
27540
|
logger_default.debug("Context file not found for metrics", { file, error: getErrorMessage(error) });
|
|
@@ -27018,8 +27542,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
27018
27542
|
}
|
|
27019
27543
|
for (const agent of agents) {
|
|
27020
27544
|
try {
|
|
27021
|
-
const agentPath =
|
|
27022
|
-
const content = await
|
|
27545
|
+
const agentPath = path57.join(this.globalPath, "agents", `${agent.name}.md`);
|
|
27546
|
+
const content = await fs54.readFile(agentPath, "utf-8");
|
|
27023
27547
|
filteredChars += content.length;
|
|
27024
27548
|
} catch (error) {
|
|
27025
27549
|
logger_default.debug("Agent file not found for metrics", {
|
|
@@ -27081,7 +27605,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
27081
27605
|
// ==========================================================================
|
|
27082
27606
|
async fileExists(filename) {
|
|
27083
27607
|
try {
|
|
27084
|
-
await
|
|
27608
|
+
await fs54.access(path57.join(this.projectPath, filename));
|
|
27085
27609
|
return true;
|
|
27086
27610
|
} catch (error) {
|
|
27087
27611
|
logger_default.debug("File not found", { filename, error: getErrorMessage(error) });
|
|
@@ -27090,8 +27614,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
27090
27614
|
}
|
|
27091
27615
|
async getCliVersion() {
|
|
27092
27616
|
try {
|
|
27093
|
-
const pkgPath =
|
|
27094
|
-
const pkg = JSON.parse(await
|
|
27617
|
+
const pkgPath = path57.join(__dirname, "..", "..", "package.json");
|
|
27618
|
+
const pkg = JSON.parse(await fs54.readFile(pkgPath, "utf-8"));
|
|
27095
27619
|
return pkg.version || "0.0.0";
|
|
27096
27620
|
} catch (error) {
|
|
27097
27621
|
logger_default.debug("Failed to read CLI version", { error: getErrorMessage(error) });
|
|
@@ -27252,22 +27776,22 @@ __export(uninstall_exports, {
|
|
|
27252
27776
|
uninstall: () => uninstall
|
|
27253
27777
|
});
|
|
27254
27778
|
import { execSync as execSync3 } from "node:child_process";
|
|
27255
|
-
import
|
|
27779
|
+
import fs55 from "node:fs/promises";
|
|
27256
27780
|
import os17 from "node:os";
|
|
27257
|
-
import
|
|
27781
|
+
import path58 from "node:path";
|
|
27258
27782
|
import readline2 from "node:readline";
|
|
27259
27783
|
import chalk12 from "chalk";
|
|
27260
27784
|
async function getDirectorySize(dirPath) {
|
|
27261
27785
|
let totalSize = 0;
|
|
27262
27786
|
try {
|
|
27263
|
-
const entries = await
|
|
27787
|
+
const entries = await fs55.readdir(dirPath, { withFileTypes: true });
|
|
27264
27788
|
for (const entry of entries) {
|
|
27265
|
-
const entryPath =
|
|
27789
|
+
const entryPath = path58.join(dirPath, entry.name);
|
|
27266
27790
|
if (entry.isDirectory()) {
|
|
27267
27791
|
totalSize += await getDirectorySize(entryPath);
|
|
27268
27792
|
} else {
|
|
27269
27793
|
try {
|
|
27270
|
-
const stats = await
|
|
27794
|
+
const stats = await fs55.stat(entryPath);
|
|
27271
27795
|
totalSize += stats.size;
|
|
27272
27796
|
} catch {
|
|
27273
27797
|
}
|
|
@@ -27286,7 +27810,7 @@ function formatSize(bytes) {
|
|
|
27286
27810
|
}
|
|
27287
27811
|
async function countDirectoryItems(dirPath) {
|
|
27288
27812
|
try {
|
|
27289
|
-
const entries = await
|
|
27813
|
+
const entries = await fs55.readdir(dirPath, { withFileTypes: true });
|
|
27290
27814
|
return entries.filter((e) => e.isDirectory()).length;
|
|
27291
27815
|
} catch {
|
|
27292
27816
|
return 0;
|
|
@@ -27319,7 +27843,7 @@ async function gatherUninstallItems() {
|
|
|
27319
27843
|
const providerPaths = getProviderPaths();
|
|
27320
27844
|
const prjctCliPath = path_manager_default.getGlobalBasePath();
|
|
27321
27845
|
const prjctCliExists = await fileExists(prjctCliPath);
|
|
27322
|
-
const projectCount = prjctCliExists ? await countDirectoryItems(
|
|
27846
|
+
const projectCount = prjctCliExists ? await countDirectoryItems(path58.join(prjctCliPath, "projects")) : 0;
|
|
27323
27847
|
const prjctCliSize = prjctCliExists ? await getDirectorySize(prjctCliPath) : 0;
|
|
27324
27848
|
items.push({
|
|
27325
27849
|
path: prjctCliPath,
|
|
@@ -27329,12 +27853,12 @@ async function gatherUninstallItems() {
|
|
|
27329
27853
|
count: projectCount,
|
|
27330
27854
|
exists: prjctCliExists
|
|
27331
27855
|
});
|
|
27332
|
-
const claudeMdPath =
|
|
27856
|
+
const claudeMdPath = path58.join(providerPaths.claude.config, "CLAUDE.md");
|
|
27333
27857
|
const claudeMdExists = await fileExists(claudeMdPath);
|
|
27334
27858
|
let hasPrjctSection = false;
|
|
27335
27859
|
if (claudeMdExists) {
|
|
27336
27860
|
try {
|
|
27337
|
-
const content = await
|
|
27861
|
+
const content = await fs55.readFile(claudeMdPath, "utf-8");
|
|
27338
27862
|
hasPrjctSection = content.includes(PRJCT_START_MARKER) && content.includes(PRJCT_END_MARKER);
|
|
27339
27863
|
} catch {
|
|
27340
27864
|
}
|
|
@@ -27363,7 +27887,7 @@ async function gatherUninstallItems() {
|
|
|
27363
27887
|
description: "Claude router",
|
|
27364
27888
|
exists: claudeRouterExists
|
|
27365
27889
|
});
|
|
27366
|
-
const statusLinePath =
|
|
27890
|
+
const statusLinePath = path58.join(providerPaths.claude.config, "prjct-statusline.sh");
|
|
27367
27891
|
const statusLineExists = await fileExists(statusLinePath);
|
|
27368
27892
|
items.push({
|
|
27369
27893
|
path: statusLinePath,
|
|
@@ -27379,12 +27903,12 @@ async function gatherUninstallItems() {
|
|
|
27379
27903
|
description: "Gemini router",
|
|
27380
27904
|
exists: geminiRouterExists
|
|
27381
27905
|
});
|
|
27382
|
-
const geminiMdPath =
|
|
27906
|
+
const geminiMdPath = path58.join(providerPaths.gemini.config, "GEMINI.md");
|
|
27383
27907
|
const geminiMdExists = await fileExists(geminiMdPath);
|
|
27384
27908
|
let hasGeminiPrjctSection = false;
|
|
27385
27909
|
if (geminiMdExists) {
|
|
27386
27910
|
try {
|
|
27387
|
-
const content = await
|
|
27911
|
+
const content = await fs55.readFile(geminiMdPath, "utf-8");
|
|
27388
27912
|
hasGeminiPrjctSection = content.includes(PRJCT_START_MARKER) && content.includes(PRJCT_END_MARKER);
|
|
27389
27913
|
} catch {
|
|
27390
27914
|
}
|
|
@@ -27401,7 +27925,7 @@ async function gatherUninstallItems() {
|
|
|
27401
27925
|
}
|
|
27402
27926
|
async function removePrjctSection(filePath) {
|
|
27403
27927
|
try {
|
|
27404
|
-
const content = await
|
|
27928
|
+
const content = await fs55.readFile(filePath, "utf-8");
|
|
27405
27929
|
if (!content.includes(PRJCT_START_MARKER) || !content.includes(PRJCT_END_MARKER)) {
|
|
27406
27930
|
return false;
|
|
27407
27931
|
}
|
|
@@ -27410,9 +27934,9 @@ async function removePrjctSection(filePath) {
|
|
|
27410
27934
|
let newContent = content.substring(0, startIndex) + content.substring(endIndex);
|
|
27411
27935
|
newContent = newContent.replace(/\n{3,}/g, "\n\n").trim();
|
|
27412
27936
|
if (!newContent || newContent.trim().length === 0) {
|
|
27413
|
-
await
|
|
27937
|
+
await fs55.unlink(filePath);
|
|
27414
27938
|
} else {
|
|
27415
|
-
await
|
|
27939
|
+
await fs55.writeFile(filePath, `${newContent}
|
|
27416
27940
|
`, "utf-8");
|
|
27417
27941
|
}
|
|
27418
27942
|
return true;
|
|
@@ -27423,12 +27947,12 @@ async function removePrjctSection(filePath) {
|
|
|
27423
27947
|
async function createBackup3() {
|
|
27424
27948
|
const homeDir = os17.homedir();
|
|
27425
27949
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
|
|
27426
|
-
const backupDir =
|
|
27950
|
+
const backupDir = path58.join(homeDir, `.prjct-backup-${timestamp}`);
|
|
27427
27951
|
try {
|
|
27428
|
-
await
|
|
27952
|
+
await fs55.mkdir(backupDir, { recursive: true });
|
|
27429
27953
|
const prjctCliPath = path_manager_default.getGlobalBasePath();
|
|
27430
27954
|
if (await fileExists(prjctCliPath)) {
|
|
27431
|
-
await copyDirectory(prjctCliPath,
|
|
27955
|
+
await copyDirectory(prjctCliPath, path58.join(backupDir, ".prjct-cli"));
|
|
27432
27956
|
}
|
|
27433
27957
|
return backupDir;
|
|
27434
27958
|
} catch {
|
|
@@ -27436,15 +27960,15 @@ async function createBackup3() {
|
|
|
27436
27960
|
}
|
|
27437
27961
|
}
|
|
27438
27962
|
async function copyDirectory(src, dest) {
|
|
27439
|
-
await
|
|
27440
|
-
const entries = await
|
|
27963
|
+
await fs55.mkdir(dest, { recursive: true });
|
|
27964
|
+
const entries = await fs55.readdir(src, { withFileTypes: true });
|
|
27441
27965
|
for (const entry of entries) {
|
|
27442
|
-
const srcPath =
|
|
27443
|
-
const destPath =
|
|
27966
|
+
const srcPath = path58.join(src, entry.name);
|
|
27967
|
+
const destPath = path58.join(dest, entry.name);
|
|
27444
27968
|
if (entry.isDirectory()) {
|
|
27445
27969
|
await copyDirectory(srcPath, destPath);
|
|
27446
27970
|
} else {
|
|
27447
|
-
await
|
|
27971
|
+
await fs55.copyFile(srcPath, destPath);
|
|
27448
27972
|
}
|
|
27449
27973
|
}
|
|
27450
27974
|
}
|
|
@@ -27460,10 +27984,10 @@ async function performUninstall(items, installation, options) {
|
|
|
27460
27984
|
deleted.push(item.path);
|
|
27461
27985
|
}
|
|
27462
27986
|
} else if (item.type === "directory") {
|
|
27463
|
-
await
|
|
27987
|
+
await fs55.rm(item.path, { recursive: true, force: true });
|
|
27464
27988
|
deleted.push(item.path);
|
|
27465
27989
|
} else if (item.type === "file") {
|
|
27466
|
-
await
|
|
27990
|
+
await fs55.unlink(item.path);
|
|
27467
27991
|
deleted.push(item.path);
|
|
27468
27992
|
}
|
|
27469
27993
|
} catch (error) {
|
|
@@ -27640,7 +28164,7 @@ __export(watch_service_exports, {
|
|
|
27640
28164
|
WatchService: () => WatchService,
|
|
27641
28165
|
watchService: () => watchService
|
|
27642
28166
|
});
|
|
27643
|
-
import
|
|
28167
|
+
import path59 from "node:path";
|
|
27644
28168
|
import chalk13 from "chalk";
|
|
27645
28169
|
import chokidar from "chokidar";
|
|
27646
28170
|
var TRIGGER_PATTERNS, IGNORE_PATTERNS2, WatchService, watchService;
|
|
@@ -27861,7 +28385,7 @@ ${chalk13.dim(`[${timestamp}]`)} ${chalk13.cyan("\u27F3")} ${filesSummary} chang
|
|
|
27861
28385
|
printStartup() {
|
|
27862
28386
|
console.log("");
|
|
27863
28387
|
console.log(chalk13.cyan("\u{1F441}\uFE0F Watching for changes..."));
|
|
27864
|
-
console.log(chalk13.dim(` Project: ${
|
|
28388
|
+
console.log(chalk13.dim(` Project: ${path59.basename(this.projectPath)}`));
|
|
27865
28389
|
console.log(chalk13.dim(` Debounce: ${this.options.debounceMs}ms`));
|
|
27866
28390
|
console.log(chalk13.dim(` Min interval: ${this.options.minIntervalMs / 1e3}s`));
|
|
27867
28391
|
console.log("");
|
|
@@ -28592,9 +29116,9 @@ __export(setup_exports, {
|
|
|
28592
29116
|
run: () => run
|
|
28593
29117
|
});
|
|
28594
29118
|
import { execSync as execSync4 } from "node:child_process";
|
|
28595
|
-
import
|
|
29119
|
+
import fs56 from "node:fs/promises";
|
|
28596
29120
|
import os18 from "node:os";
|
|
28597
|
-
import
|
|
29121
|
+
import path60 from "node:path";
|
|
28598
29122
|
import chalk15 from "chalk";
|
|
28599
29123
|
async function installAICLI(provider) {
|
|
28600
29124
|
const packageName = provider.name === "claude" ? "@anthropic-ai/claude-code" : "@google/gemini-cli";
|
|
@@ -28733,12 +29257,12 @@ async function run() {
|
|
|
28733
29257
|
}
|
|
28734
29258
|
async function installGeminiRouter() {
|
|
28735
29259
|
try {
|
|
28736
|
-
const geminiCommandsDir =
|
|
28737
|
-
const routerSource =
|
|
28738
|
-
const routerDest =
|
|
28739
|
-
await
|
|
29260
|
+
const geminiCommandsDir = path60.join(os18.homedir(), ".gemini", "commands");
|
|
29261
|
+
const routerSource = path60.join(PACKAGE_ROOT, "templates", "commands", "p.toml");
|
|
29262
|
+
const routerDest = path60.join(geminiCommandsDir, "p.toml");
|
|
29263
|
+
await fs56.mkdir(geminiCommandsDir, { recursive: true });
|
|
28740
29264
|
if (await fileExists(routerSource)) {
|
|
28741
|
-
await
|
|
29265
|
+
await fs56.copyFile(routerSource, routerDest);
|
|
28742
29266
|
return true;
|
|
28743
29267
|
}
|
|
28744
29268
|
return false;
|
|
@@ -28749,15 +29273,15 @@ async function installGeminiRouter() {
|
|
|
28749
29273
|
}
|
|
28750
29274
|
async function installGeminiGlobalConfig() {
|
|
28751
29275
|
try {
|
|
28752
|
-
const geminiDir =
|
|
28753
|
-
const globalConfigPath =
|
|
28754
|
-
const templatePath =
|
|
28755
|
-
await
|
|
28756
|
-
const templateContent = await
|
|
29276
|
+
const geminiDir = path60.join(os18.homedir(), ".gemini");
|
|
29277
|
+
const globalConfigPath = path60.join(geminiDir, "GEMINI.md");
|
|
29278
|
+
const templatePath = path60.join(PACKAGE_ROOT, "templates", "global", "GEMINI.md");
|
|
29279
|
+
await fs56.mkdir(geminiDir, { recursive: true });
|
|
29280
|
+
const templateContent = await fs56.readFile(templatePath, "utf-8");
|
|
28757
29281
|
let existingContent = "";
|
|
28758
29282
|
let configExists = false;
|
|
28759
29283
|
try {
|
|
28760
|
-
existingContent = await
|
|
29284
|
+
existingContent = await fs56.readFile(globalConfigPath, "utf-8");
|
|
28761
29285
|
configExists = true;
|
|
28762
29286
|
} catch (error) {
|
|
28763
29287
|
if (isNotFoundError(error)) {
|
|
@@ -28767,7 +29291,7 @@ async function installGeminiGlobalConfig() {
|
|
|
28767
29291
|
}
|
|
28768
29292
|
}
|
|
28769
29293
|
if (!configExists) {
|
|
28770
|
-
await
|
|
29294
|
+
await fs56.writeFile(globalConfigPath, templateContent, "utf-8");
|
|
28771
29295
|
return { success: true, action: "created" };
|
|
28772
29296
|
}
|
|
28773
29297
|
const startMarker = "<!-- prjct:start - DO NOT REMOVE THIS MARKER -->";
|
|
@@ -28777,7 +29301,7 @@ async function installGeminiGlobalConfig() {
|
|
|
28777
29301
|
const updatedContent2 = `${existingContent}
|
|
28778
29302
|
|
|
28779
29303
|
${templateContent}`;
|
|
28780
|
-
await
|
|
29304
|
+
await fs56.writeFile(globalConfigPath, updatedContent2, "utf-8");
|
|
28781
29305
|
return { success: true, action: "appended" };
|
|
28782
29306
|
}
|
|
28783
29307
|
const beforeMarker = existingContent.substring(0, existingContent.indexOf(startMarker));
|
|
@@ -28789,7 +29313,7 @@ ${templateContent}`;
|
|
|
28789
29313
|
templateContent.indexOf(endMarker) + endMarker.length
|
|
28790
29314
|
);
|
|
28791
29315
|
const updatedContent = beforeMarker + prjctSection + afterMarker;
|
|
28792
|
-
await
|
|
29316
|
+
await fs56.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
28793
29317
|
return { success: true, action: "updated" };
|
|
28794
29318
|
} catch (error) {
|
|
28795
29319
|
logger_default.warn(`Gemini config warning: ${getErrorMessage2(error)}`);
|
|
@@ -28798,18 +29322,18 @@ ${templateContent}`;
|
|
|
28798
29322
|
}
|
|
28799
29323
|
async function installAntigravitySkill() {
|
|
28800
29324
|
try {
|
|
28801
|
-
const antigravitySkillsDir =
|
|
28802
|
-
const prjctSkillDir =
|
|
28803
|
-
const skillMdPath =
|
|
28804
|
-
const templatePath =
|
|
28805
|
-
await
|
|
29325
|
+
const antigravitySkillsDir = path60.join(os18.homedir(), ".gemini", "antigravity", "skills");
|
|
29326
|
+
const prjctSkillDir = path60.join(antigravitySkillsDir, "prjct");
|
|
29327
|
+
const skillMdPath = path60.join(prjctSkillDir, "SKILL.md");
|
|
29328
|
+
const templatePath = path60.join(PACKAGE_ROOT, "templates", "antigravity", "SKILL.md");
|
|
29329
|
+
await fs56.mkdir(prjctSkillDir, { recursive: true });
|
|
28806
29330
|
const skillExists = await fileExists(skillMdPath);
|
|
28807
29331
|
if (!await fileExists(templatePath)) {
|
|
28808
29332
|
logger_default.warn("Antigravity SKILL.md template not found");
|
|
28809
29333
|
return { success: false, action: null };
|
|
28810
29334
|
}
|
|
28811
|
-
const templateContent = await
|
|
28812
|
-
await
|
|
29335
|
+
const templateContent = await fs56.readFile(templatePath, "utf-8");
|
|
29336
|
+
await fs56.writeFile(skillMdPath, templateContent, "utf-8");
|
|
28813
29337
|
return { success: true, action: skillExists ? "updated" : "created" };
|
|
28814
29338
|
} catch (error) {
|
|
28815
29339
|
logger_default.warn(`Antigravity skill warning: ${getErrorMessage2(error)}`);
|
|
@@ -28828,24 +29352,24 @@ async function installCursorProject(projectRoot) {
|
|
|
28828
29352
|
gitignoreUpdated: false
|
|
28829
29353
|
};
|
|
28830
29354
|
try {
|
|
28831
|
-
const cursorDir =
|
|
28832
|
-
const rulesDir =
|
|
28833
|
-
const commandsDir =
|
|
28834
|
-
const routerMdcDest =
|
|
28835
|
-
const routerMdcSource =
|
|
28836
|
-
const cursorCommandsSource =
|
|
28837
|
-
await
|
|
28838
|
-
await
|
|
29355
|
+
const cursorDir = path60.join(projectRoot, ".cursor");
|
|
29356
|
+
const rulesDir = path60.join(cursorDir, "rules");
|
|
29357
|
+
const commandsDir = path60.join(cursorDir, "commands");
|
|
29358
|
+
const routerMdcDest = path60.join(rulesDir, "prjct.mdc");
|
|
29359
|
+
const routerMdcSource = path60.join(PACKAGE_ROOT, "templates", "cursor", "router.mdc");
|
|
29360
|
+
const cursorCommandsSource = path60.join(PACKAGE_ROOT, "templates", "cursor", "commands");
|
|
29361
|
+
await fs56.mkdir(rulesDir, { recursive: true });
|
|
29362
|
+
await fs56.mkdir(commandsDir, { recursive: true });
|
|
28839
29363
|
if (await fileExists(routerMdcSource)) {
|
|
28840
|
-
await
|
|
29364
|
+
await fs56.copyFile(routerMdcSource, routerMdcDest);
|
|
28841
29365
|
result.rulesCreated = true;
|
|
28842
29366
|
}
|
|
28843
29367
|
if (await fileExists(cursorCommandsSource)) {
|
|
28844
|
-
const commandFiles = (await
|
|
29368
|
+
const commandFiles = (await fs56.readdir(cursorCommandsSource)).filter((f) => f.endsWith(".md"));
|
|
28845
29369
|
for (const file of commandFiles) {
|
|
28846
|
-
const src =
|
|
28847
|
-
const dest =
|
|
28848
|
-
await
|
|
29370
|
+
const src = path60.join(cursorCommandsSource, file);
|
|
29371
|
+
const dest = path60.join(commandsDir, file);
|
|
29372
|
+
await fs56.copyFile(src, dest);
|
|
28849
29373
|
}
|
|
28850
29374
|
result.commandsCreated = commandFiles.length > 0;
|
|
28851
29375
|
}
|
|
@@ -28859,7 +29383,7 @@ async function installCursorProject(projectRoot) {
|
|
|
28859
29383
|
}
|
|
28860
29384
|
async function addCursorToGitignore(projectRoot) {
|
|
28861
29385
|
try {
|
|
28862
|
-
const gitignorePath =
|
|
29386
|
+
const gitignorePath = path60.join(projectRoot, ".gitignore");
|
|
28863
29387
|
const entriesToAdd = [
|
|
28864
29388
|
"# prjct Cursor routers (regenerated per-developer)",
|
|
28865
29389
|
".cursor/rules/prjct.mdc",
|
|
@@ -28874,7 +29398,7 @@ async function addCursorToGitignore(projectRoot) {
|
|
|
28874
29398
|
let content = "";
|
|
28875
29399
|
let configExists = false;
|
|
28876
29400
|
try {
|
|
28877
|
-
content = await
|
|
29401
|
+
content = await fs56.readFile(gitignorePath, "utf-8");
|
|
28878
29402
|
configExists = true;
|
|
28879
29403
|
} catch (error) {
|
|
28880
29404
|
if (!isNotFoundError(error)) {
|
|
@@ -28889,7 +29413,7 @@ async function addCursorToGitignore(projectRoot) {
|
|
|
28889
29413
|
${entriesToAdd.join("\n")}
|
|
28890
29414
|
` : `${entriesToAdd.join("\n")}
|
|
28891
29415
|
`;
|
|
28892
|
-
await
|
|
29416
|
+
await fs56.writeFile(gitignorePath, newContent, "utf-8");
|
|
28893
29417
|
return true;
|
|
28894
29418
|
} catch (error) {
|
|
28895
29419
|
logger_default.warn(`Gitignore update warning: ${getErrorMessage2(error)}`);
|
|
@@ -28897,11 +29421,11 @@ ${entriesToAdd.join("\n")}
|
|
|
28897
29421
|
}
|
|
28898
29422
|
}
|
|
28899
29423
|
async function hasCursorProject(projectRoot) {
|
|
28900
|
-
return await fileExists(
|
|
29424
|
+
return await fileExists(path60.join(projectRoot, ".cursor"));
|
|
28901
29425
|
}
|
|
28902
29426
|
async function needsCursorRegeneration(projectRoot) {
|
|
28903
|
-
const cursorDir =
|
|
28904
|
-
const routerPath =
|
|
29427
|
+
const cursorDir = path60.join(projectRoot, ".cursor");
|
|
29428
|
+
const routerPath = path60.join(cursorDir, "rules", "prjct.mdc");
|
|
28905
29429
|
return await fileExists(cursorDir) && !await fileExists(routerPath);
|
|
28906
29430
|
}
|
|
28907
29431
|
async function installWindsurfProject(projectRoot) {
|
|
@@ -28912,26 +29436,26 @@ async function installWindsurfProject(projectRoot) {
|
|
|
28912
29436
|
gitignoreUpdated: false
|
|
28913
29437
|
};
|
|
28914
29438
|
try {
|
|
28915
|
-
const windsurfDir =
|
|
28916
|
-
const rulesDir =
|
|
28917
|
-
const workflowsDir =
|
|
28918
|
-
const routerDest =
|
|
28919
|
-
const routerSource =
|
|
28920
|
-
const windsurfWorkflowsSource =
|
|
28921
|
-
await
|
|
28922
|
-
await
|
|
29439
|
+
const windsurfDir = path60.join(projectRoot, ".windsurf");
|
|
29440
|
+
const rulesDir = path60.join(windsurfDir, "rules");
|
|
29441
|
+
const workflowsDir = path60.join(windsurfDir, "workflows");
|
|
29442
|
+
const routerDest = path60.join(rulesDir, "prjct.md");
|
|
29443
|
+
const routerSource = path60.join(PACKAGE_ROOT, "templates", "windsurf", "router.md");
|
|
29444
|
+
const windsurfWorkflowsSource = path60.join(PACKAGE_ROOT, "templates", "windsurf", "workflows");
|
|
29445
|
+
await fs56.mkdir(rulesDir, { recursive: true });
|
|
29446
|
+
await fs56.mkdir(workflowsDir, { recursive: true });
|
|
28923
29447
|
if (await fileExists(routerSource)) {
|
|
28924
|
-
await
|
|
29448
|
+
await fs56.copyFile(routerSource, routerDest);
|
|
28925
29449
|
result.rulesCreated = true;
|
|
28926
29450
|
}
|
|
28927
29451
|
if (await fileExists(windsurfWorkflowsSource)) {
|
|
28928
|
-
const workflowFiles = (await
|
|
29452
|
+
const workflowFiles = (await fs56.readdir(windsurfWorkflowsSource)).filter(
|
|
28929
29453
|
(f) => f.endsWith(".md")
|
|
28930
29454
|
);
|
|
28931
29455
|
for (const file of workflowFiles) {
|
|
28932
|
-
const src =
|
|
28933
|
-
const dest =
|
|
28934
|
-
await
|
|
29456
|
+
const src = path60.join(windsurfWorkflowsSource, file);
|
|
29457
|
+
const dest = path60.join(workflowsDir, file);
|
|
29458
|
+
await fs56.copyFile(src, dest);
|
|
28935
29459
|
}
|
|
28936
29460
|
result.workflowsCreated = workflowFiles.length > 0;
|
|
28937
29461
|
}
|
|
@@ -28945,7 +29469,7 @@ async function installWindsurfProject(projectRoot) {
|
|
|
28945
29469
|
}
|
|
28946
29470
|
async function addWindsurfToGitignore(projectRoot) {
|
|
28947
29471
|
try {
|
|
28948
|
-
const gitignorePath =
|
|
29472
|
+
const gitignorePath = path60.join(projectRoot, ".gitignore");
|
|
28949
29473
|
const entriesToAdd = [
|
|
28950
29474
|
"# prjct Windsurf routers (regenerated per-developer)",
|
|
28951
29475
|
".windsurf/rules/prjct.md",
|
|
@@ -28960,7 +29484,7 @@ async function addWindsurfToGitignore(projectRoot) {
|
|
|
28960
29484
|
let content = "";
|
|
28961
29485
|
let configExists = false;
|
|
28962
29486
|
try {
|
|
28963
|
-
content = await
|
|
29487
|
+
content = await fs56.readFile(gitignorePath, "utf-8");
|
|
28964
29488
|
configExists = true;
|
|
28965
29489
|
} catch (error) {
|
|
28966
29490
|
if (!isNotFoundError(error)) {
|
|
@@ -28975,7 +29499,7 @@ async function addWindsurfToGitignore(projectRoot) {
|
|
|
28975
29499
|
${entriesToAdd.join("\n")}
|
|
28976
29500
|
` : `${entriesToAdd.join("\n")}
|
|
28977
29501
|
`;
|
|
28978
|
-
await
|
|
29502
|
+
await fs56.writeFile(gitignorePath, newContent, "utf-8");
|
|
28979
29503
|
return true;
|
|
28980
29504
|
} catch (error) {
|
|
28981
29505
|
logger_default.warn(`Gitignore update warning: ${getErrorMessage2(error)}`);
|
|
@@ -28983,32 +29507,32 @@ ${entriesToAdd.join("\n")}
|
|
|
28983
29507
|
}
|
|
28984
29508
|
}
|
|
28985
29509
|
async function hasWindsurfProject(projectRoot) {
|
|
28986
|
-
return await fileExists(
|
|
29510
|
+
return await fileExists(path60.join(projectRoot, ".windsurf"));
|
|
28987
29511
|
}
|
|
28988
29512
|
async function needsWindsurfRegeneration(projectRoot) {
|
|
28989
|
-
const windsurfDir =
|
|
28990
|
-
const routerPath =
|
|
29513
|
+
const windsurfDir = path60.join(projectRoot, ".windsurf");
|
|
29514
|
+
const routerPath = path60.join(windsurfDir, "rules", "prjct.md");
|
|
28991
29515
|
return await fileExists(windsurfDir) && !await fileExists(routerPath);
|
|
28992
29516
|
}
|
|
28993
29517
|
async function migrateProjectsCliVersion() {
|
|
28994
29518
|
try {
|
|
28995
|
-
const projectsDir =
|
|
29519
|
+
const projectsDir = path60.join(os18.homedir(), ".prjct-cli", "projects");
|
|
28996
29520
|
if (!await fileExists(projectsDir)) {
|
|
28997
29521
|
return;
|
|
28998
29522
|
}
|
|
28999
|
-
const projectDirs = (await
|
|
29523
|
+
const projectDirs = (await fs56.readdir(projectsDir, { withFileTypes: true })).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
29000
29524
|
let migrated = 0;
|
|
29001
29525
|
for (const projectId of projectDirs) {
|
|
29002
|
-
const projectJsonPath =
|
|
29526
|
+
const projectJsonPath = path60.join(projectsDir, projectId, "project.json");
|
|
29003
29527
|
if (!await fileExists(projectJsonPath)) {
|
|
29004
29528
|
continue;
|
|
29005
29529
|
}
|
|
29006
29530
|
try {
|
|
29007
|
-
const content = await
|
|
29531
|
+
const content = await fs56.readFile(projectJsonPath, "utf8");
|
|
29008
29532
|
const project = JSON.parse(content);
|
|
29009
29533
|
if (project.cliVersion !== VERSION) {
|
|
29010
29534
|
project.cliVersion = VERSION;
|
|
29011
|
-
await
|
|
29535
|
+
await fs56.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
|
|
29012
29536
|
migrated++;
|
|
29013
29537
|
}
|
|
29014
29538
|
} catch (error) {
|
|
@@ -29030,7 +29554,7 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
|
|
|
29030
29554
|
let settings = {};
|
|
29031
29555
|
if (await fileExists(settingsPath)) {
|
|
29032
29556
|
try {
|
|
29033
|
-
settings = JSON.parse(await
|
|
29557
|
+
settings = JSON.parse(await fs56.readFile(settingsPath, "utf8"));
|
|
29034
29558
|
} catch (error) {
|
|
29035
29559
|
if (!(error instanceof SyntaxError)) {
|
|
29036
29560
|
throw error;
|
|
@@ -29038,42 +29562,42 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
|
|
|
29038
29562
|
}
|
|
29039
29563
|
}
|
|
29040
29564
|
settings.statusLine = { type: "command", command: statusLinePath };
|
|
29041
|
-
await
|
|
29565
|
+
await fs56.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
29042
29566
|
}
|
|
29043
29567
|
async function installStatusLine() {
|
|
29044
29568
|
try {
|
|
29045
|
-
const claudeDir =
|
|
29046
|
-
const settingsPath =
|
|
29047
|
-
const claudeStatusLinePath =
|
|
29048
|
-
const prjctStatusLineDir =
|
|
29049
|
-
const prjctStatusLinePath =
|
|
29050
|
-
const prjctThemesDir =
|
|
29051
|
-
const prjctLibDir =
|
|
29052
|
-
const prjctComponentsDir =
|
|
29053
|
-
const prjctConfigPath =
|
|
29054
|
-
const assetsDir =
|
|
29055
|
-
const sourceScript =
|
|
29056
|
-
const sourceThemeDir =
|
|
29057
|
-
const sourceLibDir =
|
|
29058
|
-
const sourceComponentsDir =
|
|
29059
|
-
const sourceConfigPath =
|
|
29569
|
+
const claudeDir = path60.join(os18.homedir(), ".claude");
|
|
29570
|
+
const settingsPath = path60.join(claudeDir, "settings.json");
|
|
29571
|
+
const claudeStatusLinePath = path60.join(claudeDir, "prjct-statusline.sh");
|
|
29572
|
+
const prjctStatusLineDir = path60.join(os18.homedir(), ".prjct-cli", "statusline");
|
|
29573
|
+
const prjctStatusLinePath = path60.join(prjctStatusLineDir, "statusline.sh");
|
|
29574
|
+
const prjctThemesDir = path60.join(prjctStatusLineDir, "themes");
|
|
29575
|
+
const prjctLibDir = path60.join(prjctStatusLineDir, "lib");
|
|
29576
|
+
const prjctComponentsDir = path60.join(prjctStatusLineDir, "components");
|
|
29577
|
+
const prjctConfigPath = path60.join(prjctStatusLineDir, "config.json");
|
|
29578
|
+
const assetsDir = path60.join(PACKAGE_ROOT, "assets", "statusline");
|
|
29579
|
+
const sourceScript = path60.join(assetsDir, "statusline.sh");
|
|
29580
|
+
const sourceThemeDir = path60.join(assetsDir, "themes");
|
|
29581
|
+
const sourceLibDir = path60.join(assetsDir, "lib");
|
|
29582
|
+
const sourceComponentsDir = path60.join(assetsDir, "components");
|
|
29583
|
+
const sourceConfigPath = path60.join(assetsDir, "default-config.json");
|
|
29060
29584
|
if (!await fileExists(claudeDir)) {
|
|
29061
|
-
await
|
|
29585
|
+
await fs56.mkdir(claudeDir, { recursive: true });
|
|
29062
29586
|
}
|
|
29063
29587
|
if (!await fileExists(prjctStatusLineDir)) {
|
|
29064
|
-
await
|
|
29588
|
+
await fs56.mkdir(prjctStatusLineDir, { recursive: true });
|
|
29065
29589
|
}
|
|
29066
29590
|
if (!await fileExists(prjctThemesDir)) {
|
|
29067
|
-
await
|
|
29591
|
+
await fs56.mkdir(prjctThemesDir, { recursive: true });
|
|
29068
29592
|
}
|
|
29069
29593
|
if (!await fileExists(prjctLibDir)) {
|
|
29070
|
-
await
|
|
29594
|
+
await fs56.mkdir(prjctLibDir, { recursive: true });
|
|
29071
29595
|
}
|
|
29072
29596
|
if (!await fileExists(prjctComponentsDir)) {
|
|
29073
|
-
await
|
|
29597
|
+
await fs56.mkdir(prjctComponentsDir, { recursive: true });
|
|
29074
29598
|
}
|
|
29075
29599
|
if (await fileExists(prjctStatusLinePath)) {
|
|
29076
|
-
const existingContent = await
|
|
29600
|
+
const existingContent = await fs56.readFile(prjctStatusLinePath, "utf8");
|
|
29077
29601
|
if (existingContent.includes("CLI_VERSION=")) {
|
|
29078
29602
|
const versionMatch = existingContent.match(/CLI_VERSION="([^"]*)"/);
|
|
29079
29603
|
if (versionMatch && versionMatch[1] !== VERSION) {
|
|
@@ -29081,7 +29605,7 @@ async function installStatusLine() {
|
|
|
29081
29605
|
/CLI_VERSION="[^"]*"/,
|
|
29082
29606
|
`CLI_VERSION="${VERSION}"`
|
|
29083
29607
|
);
|
|
29084
|
-
await
|
|
29608
|
+
await fs56.writeFile(prjctStatusLinePath, updatedContent, { mode: 493 });
|
|
29085
29609
|
}
|
|
29086
29610
|
await installStatusLineModules(sourceLibDir, prjctLibDir);
|
|
29087
29611
|
await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
|
|
@@ -29091,21 +29615,21 @@ async function installStatusLine() {
|
|
|
29091
29615
|
}
|
|
29092
29616
|
}
|
|
29093
29617
|
if (await fileExists(sourceScript)) {
|
|
29094
|
-
let scriptContent = await
|
|
29618
|
+
let scriptContent = await fs56.readFile(sourceScript, "utf8");
|
|
29095
29619
|
scriptContent = scriptContent.replace(/CLI_VERSION="[^"]*"/, `CLI_VERSION="${VERSION}"`);
|
|
29096
|
-
await
|
|
29620
|
+
await fs56.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
|
|
29097
29621
|
await installStatusLineModules(sourceLibDir, prjctLibDir);
|
|
29098
29622
|
await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
|
|
29099
29623
|
if (await fileExists(sourceThemeDir)) {
|
|
29100
|
-
const themes = await
|
|
29624
|
+
const themes = await fs56.readdir(sourceThemeDir);
|
|
29101
29625
|
for (const theme of themes) {
|
|
29102
|
-
const src =
|
|
29103
|
-
const dest =
|
|
29104
|
-
await
|
|
29626
|
+
const src = path60.join(sourceThemeDir, theme);
|
|
29627
|
+
const dest = path60.join(prjctThemesDir, theme);
|
|
29628
|
+
await fs56.copyFile(src, dest);
|
|
29105
29629
|
}
|
|
29106
29630
|
}
|
|
29107
29631
|
if (!await fileExists(prjctConfigPath) && await fileExists(sourceConfigPath)) {
|
|
29108
|
-
await
|
|
29632
|
+
await fs56.copyFile(sourceConfigPath, prjctConfigPath);
|
|
29109
29633
|
}
|
|
29110
29634
|
} else {
|
|
29111
29635
|
const scriptContent = `#!/bin/bash
|
|
@@ -29140,7 +29664,7 @@ if [ -f "$CONFIG" ]; then
|
|
|
29140
29664
|
fi
|
|
29141
29665
|
echo "prjct"
|
|
29142
29666
|
`;
|
|
29143
|
-
await
|
|
29667
|
+
await fs56.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
|
|
29144
29668
|
}
|
|
29145
29669
|
await ensureStatusLineSymlink(claudeStatusLinePath, prjctStatusLinePath);
|
|
29146
29670
|
await ensureStatusLineSettings(settingsPath, claudeStatusLinePath);
|
|
@@ -29152,10 +29676,10 @@ echo "prjct"
|
|
|
29152
29676
|
}
|
|
29153
29677
|
async function installContext7MCP() {
|
|
29154
29678
|
try {
|
|
29155
|
-
const claudeDir =
|
|
29156
|
-
const mcpConfigPath =
|
|
29679
|
+
const claudeDir = path60.join(os18.homedir(), ".claude");
|
|
29680
|
+
const mcpConfigPath = path60.join(claudeDir, "mcp.json");
|
|
29157
29681
|
if (!await fileExists(claudeDir)) {
|
|
29158
|
-
await
|
|
29682
|
+
await fs56.mkdir(claudeDir, { recursive: true });
|
|
29159
29683
|
}
|
|
29160
29684
|
const context7Config = {
|
|
29161
29685
|
mcpServers: {
|
|
@@ -29166,16 +29690,16 @@ async function installContext7MCP() {
|
|
|
29166
29690
|
}
|
|
29167
29691
|
};
|
|
29168
29692
|
if (await fileExists(mcpConfigPath)) {
|
|
29169
|
-
const existingContent = await
|
|
29693
|
+
const existingContent = await fs56.readFile(mcpConfigPath, "utf-8");
|
|
29170
29694
|
const existingConfig = JSON.parse(existingContent);
|
|
29171
29695
|
if (existingConfig.mcpServers?.context7) {
|
|
29172
29696
|
return;
|
|
29173
29697
|
}
|
|
29174
29698
|
existingConfig.mcpServers = existingConfig.mcpServers || {};
|
|
29175
29699
|
existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
|
|
29176
|
-
await
|
|
29700
|
+
await fs56.writeFile(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
|
|
29177
29701
|
} else {
|
|
29178
|
-
await
|
|
29702
|
+
await fs56.writeFile(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
|
|
29179
29703
|
}
|
|
29180
29704
|
} catch (error) {
|
|
29181
29705
|
logger_default.warn(`Context7 MCP setup warning: ${getErrorMessage2(error)}`);
|
|
@@ -29185,34 +29709,34 @@ async function installStatusLineModules(sourceDir, destDir) {
|
|
|
29185
29709
|
if (!await fileExists(sourceDir)) {
|
|
29186
29710
|
return;
|
|
29187
29711
|
}
|
|
29188
|
-
const files = await
|
|
29712
|
+
const files = await fs56.readdir(sourceDir);
|
|
29189
29713
|
for (const file of files) {
|
|
29190
29714
|
if (file.endsWith(".sh")) {
|
|
29191
|
-
const src =
|
|
29192
|
-
const dest =
|
|
29193
|
-
await
|
|
29194
|
-
await
|
|
29715
|
+
const src = path60.join(sourceDir, file);
|
|
29716
|
+
const dest = path60.join(destDir, file);
|
|
29717
|
+
await fs56.copyFile(src, dest);
|
|
29718
|
+
await fs56.chmod(dest, 493);
|
|
29195
29719
|
}
|
|
29196
29720
|
}
|
|
29197
29721
|
}
|
|
29198
29722
|
async function ensureStatusLineSymlink(linkPath, targetPath) {
|
|
29199
29723
|
try {
|
|
29200
29724
|
if (await fileExists(linkPath)) {
|
|
29201
|
-
const stats = await
|
|
29725
|
+
const stats = await fs56.lstat(linkPath);
|
|
29202
29726
|
if (stats.isSymbolicLink()) {
|
|
29203
|
-
const existingTarget = await
|
|
29727
|
+
const existingTarget = await fs56.readlink(linkPath);
|
|
29204
29728
|
if (existingTarget === targetPath) {
|
|
29205
29729
|
return;
|
|
29206
29730
|
}
|
|
29207
29731
|
}
|
|
29208
|
-
await
|
|
29732
|
+
await fs56.unlink(linkPath);
|
|
29209
29733
|
}
|
|
29210
|
-
await
|
|
29734
|
+
await fs56.symlink(targetPath, linkPath);
|
|
29211
29735
|
} catch (_error) {
|
|
29212
29736
|
try {
|
|
29213
29737
|
if (await fileExists(targetPath)) {
|
|
29214
|
-
await
|
|
29215
|
-
await
|
|
29738
|
+
await fs56.copyFile(targetPath, linkPath);
|
|
29739
|
+
await fs56.chmod(linkPath, 493);
|
|
29216
29740
|
}
|
|
29217
29741
|
} catch (copyError) {
|
|
29218
29742
|
if (!isNotFoundError(copyError)) {
|
|
@@ -29627,7 +30151,7 @@ var init_registry2 = __esm({
|
|
|
29627
30151
|
});
|
|
29628
30152
|
|
|
29629
30153
|
// core/commands/analytics.ts
|
|
29630
|
-
import
|
|
30154
|
+
import path61 from "node:path";
|
|
29631
30155
|
var AnalyticsCommands;
|
|
29632
30156
|
var init_analytics = __esm({
|
|
29633
30157
|
"core/commands/analytics.ts"() {
|
|
@@ -29654,7 +30178,7 @@ var init_analytics = __esm({
|
|
|
29654
30178
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
29655
30179
|
return { success: false, error: "No project ID found" };
|
|
29656
30180
|
}
|
|
29657
|
-
const projectName =
|
|
30181
|
+
const projectName = path61.basename(projectPath);
|
|
29658
30182
|
const currentTask = await stateStorage.getCurrentTask(projectId);
|
|
29659
30183
|
const queueTasks = await queueStorage.getActiveTasks(projectId);
|
|
29660
30184
|
const shipped = await shippedStorage.getRecent(projectId, 5);
|
|
@@ -29906,8 +30430,8 @@ ${"\u2550".repeat(50)}
|
|
|
29906
30430
|
});
|
|
29907
30431
|
|
|
29908
30432
|
// core/commands/context.ts
|
|
29909
|
-
import
|
|
29910
|
-
import
|
|
30433
|
+
import fs57 from "node:fs/promises";
|
|
30434
|
+
import path62 from "node:path";
|
|
29911
30435
|
var ContextCommands, contextCommands;
|
|
29912
30436
|
var init_context = __esm({
|
|
29913
30437
|
"core/commands/context.ts"() {
|
|
@@ -30033,8 +30557,8 @@ var init_context = __esm({
|
|
|
30033
30557
|
*/
|
|
30034
30558
|
async loadRepoAnalysis(globalPath) {
|
|
30035
30559
|
try {
|
|
30036
|
-
const analysisPath =
|
|
30037
|
-
const content = await
|
|
30560
|
+
const analysisPath = path62.join(globalPath, "analysis", "repo-analysis.json");
|
|
30561
|
+
const content = await fs57.readFile(analysisPath, "utf-8");
|
|
30038
30562
|
const data = JSON.parse(content);
|
|
30039
30563
|
return {
|
|
30040
30564
|
ecosystem: data.ecosystem || "unknown",
|
|
@@ -30053,7 +30577,7 @@ var init_context = __esm({
|
|
|
30053
30577
|
});
|
|
30054
30578
|
|
|
30055
30579
|
// core/commands/cleanup.ts
|
|
30056
|
-
import
|
|
30580
|
+
import path63 from "node:path";
|
|
30057
30581
|
async function cleanupMemory(projectPath) {
|
|
30058
30582
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
30059
30583
|
const results = { rotated: [], totalSize: 0, freedSpace: 0 };
|
|
@@ -30069,7 +30593,7 @@ async function cleanupMemory(projectPath) {
|
|
|
30069
30593
|
results.totalSize += sizeMB;
|
|
30070
30594
|
const rotated = await jsonl_helper_exports.rotateJsonLinesIfNeeded(filePath, 10);
|
|
30071
30595
|
if (rotated) {
|
|
30072
|
-
results.rotated.push(
|
|
30596
|
+
results.rotated.push(path63.basename(filePath));
|
|
30073
30597
|
results.freedSpace += sizeMB;
|
|
30074
30598
|
}
|
|
30075
30599
|
}
|
|
@@ -30176,7 +30700,7 @@ var init_cleanup = __esm({
|
|
|
30176
30700
|
});
|
|
30177
30701
|
|
|
30178
30702
|
// core/commands/design.ts
|
|
30179
|
-
import
|
|
30703
|
+
import path64 from "node:path";
|
|
30180
30704
|
async function design(target = null, options = {}, projectPath = process.cwd()) {
|
|
30181
30705
|
try {
|
|
30182
30706
|
const designType = options.type || "architecture";
|
|
@@ -30188,7 +30712,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
|
|
|
30188
30712
|
const designTarget = target || "system";
|
|
30189
30713
|
output_default.spin(`designing ${designType}...`);
|
|
30190
30714
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
30191
|
-
const designsPath =
|
|
30715
|
+
const designsPath = path64.join(
|
|
30192
30716
|
path_manager_default.getGlobalProjectPath(projectId),
|
|
30193
30717
|
"planning",
|
|
30194
30718
|
"designs"
|
|
@@ -30228,7 +30752,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
|
|
|
30228
30752
|
break;
|
|
30229
30753
|
}
|
|
30230
30754
|
const designFileName = `${designType}-${designTarget.toLowerCase().replace(/\s+/g, "-")}.md`;
|
|
30231
|
-
const designFilePath =
|
|
30755
|
+
const designFilePath = path64.join(designsPath, designFileName);
|
|
30232
30756
|
await file_helper_exports.writeFile(designFilePath, designContent);
|
|
30233
30757
|
await memoryService.log(projectPath, "design_created", {
|
|
30234
30758
|
type: designType,
|
|
@@ -30253,7 +30777,7 @@ var init_design = __esm({
|
|
|
30253
30777
|
});
|
|
30254
30778
|
|
|
30255
30779
|
// core/commands/snapshots.ts
|
|
30256
|
-
import
|
|
30780
|
+
import path65 from "node:path";
|
|
30257
30781
|
async function recover(projectPath = process.cwd()) {
|
|
30258
30782
|
try {
|
|
30259
30783
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
@@ -30305,7 +30829,7 @@ async function undo(projectPath = process.cwd()) {
|
|
|
30305
30829
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
30306
30830
|
return { success: false, error: "No project ID found" };
|
|
30307
30831
|
}
|
|
30308
|
-
const snapshotsPath =
|
|
30832
|
+
const snapshotsPath = path65.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
30309
30833
|
await file_helper_exports.ensureDir(snapshotsPath);
|
|
30310
30834
|
const { execSync: execSync5 } = await import("node:child_process");
|
|
30311
30835
|
try {
|
|
@@ -30323,7 +30847,7 @@ async function undo(projectPath = process.cwd()) {
|
|
|
30323
30847
|
cwd: projectPath,
|
|
30324
30848
|
encoding: "utf-8"
|
|
30325
30849
|
});
|
|
30326
|
-
const snapshotFile =
|
|
30850
|
+
const snapshotFile = path65.join(snapshotsPath, "history.json");
|
|
30327
30851
|
let history2 = { snapshots: [], current: -1 };
|
|
30328
30852
|
try {
|
|
30329
30853
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -30363,8 +30887,8 @@ async function redo(projectPath = process.cwd()) {
|
|
|
30363
30887
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
30364
30888
|
return { success: false, error: "No project ID found" };
|
|
30365
30889
|
}
|
|
30366
|
-
const snapshotsPath =
|
|
30367
|
-
const snapshotFile =
|
|
30890
|
+
const snapshotsPath = path65.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
30891
|
+
const snapshotFile = path65.join(snapshotsPath, "history.json");
|
|
30368
30892
|
let history2;
|
|
30369
30893
|
try {
|
|
30370
30894
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -30423,8 +30947,8 @@ async function history(projectPath = process.cwd()) {
|
|
|
30423
30947
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
30424
30948
|
return { success: false, error: "No project ID found" };
|
|
30425
30949
|
}
|
|
30426
|
-
const snapshotsPath =
|
|
30427
|
-
const snapshotFile =
|
|
30950
|
+
const snapshotsPath = path65.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
30951
|
+
const snapshotFile = path65.join(snapshotsPath, "history.json");
|
|
30428
30952
|
let snapshotHistory;
|
|
30429
30953
|
try {
|
|
30430
30954
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -30627,8 +31151,8 @@ ${chalk16.cyan("Performance Report")} ${chalk16.dim(`(last ${days} days)`)}`);
|
|
|
30627
31151
|
});
|
|
30628
31152
|
|
|
30629
31153
|
// core/commands/setup.ts
|
|
30630
|
-
import
|
|
30631
|
-
import
|
|
31154
|
+
import fs58 from "node:fs/promises";
|
|
31155
|
+
import path66 from "node:path";
|
|
30632
31156
|
import chalk17 from "chalk";
|
|
30633
31157
|
var SetupCommands;
|
|
30634
31158
|
var init_setup2 = __esm({
|
|
@@ -30757,7 +31281,7 @@ Please install it first:
|
|
|
30757
31281
|
try {
|
|
30758
31282
|
const claudeDir = path_manager_default.getClaudeDir();
|
|
30759
31283
|
const settingsPath = path_manager_default.getClaudeSettingsPath();
|
|
30760
|
-
const statusLinePath =
|
|
31284
|
+
const statusLinePath = path66.join(claudeDir, "prjct-statusline.sh");
|
|
30761
31285
|
const scriptContent = `#!/bin/bash
|
|
30762
31286
|
# prjct Status Line for Claude Code
|
|
30763
31287
|
# Shows version update notifications and current task
|
|
@@ -30815,11 +31339,11 @@ fi
|
|
|
30815
31339
|
# Default: show prjct branding
|
|
30816
31340
|
echo "\u26A1 prjct"
|
|
30817
31341
|
`;
|
|
30818
|
-
await
|
|
31342
|
+
await fs58.writeFile(statusLinePath, scriptContent, { mode: 493 });
|
|
30819
31343
|
let settings = {};
|
|
30820
31344
|
if (await fileExists(settingsPath)) {
|
|
30821
31345
|
try {
|
|
30822
|
-
settings = JSON.parse(await
|
|
31346
|
+
settings = JSON.parse(await fs58.readFile(settingsPath, "utf8"));
|
|
30823
31347
|
} catch (_error) {
|
|
30824
31348
|
}
|
|
30825
31349
|
}
|
|
@@ -30827,7 +31351,7 @@ echo "\u26A1 prjct"
|
|
|
30827
31351
|
type: "command",
|
|
30828
31352
|
command: statusLinePath
|
|
30829
31353
|
};
|
|
30830
|
-
await
|
|
31354
|
+
await fs58.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
30831
31355
|
return { success: true };
|
|
30832
31356
|
} catch (error) {
|
|
30833
31357
|
return { success: false, error: getErrorMessage2(error) };
|
|
@@ -30883,18 +31407,18 @@ echo "\u26A1 prjct"
|
|
|
30883
31407
|
});
|
|
30884
31408
|
|
|
30885
31409
|
// core/utils/project-commands.ts
|
|
30886
|
-
import
|
|
31410
|
+
import path67 from "node:path";
|
|
30887
31411
|
async function detectPackageManager(projectPath, pkg) {
|
|
30888
31412
|
const declared = pkg?.packageManager?.trim().toLowerCase();
|
|
30889
31413
|
if (declared?.startsWith("pnpm@")) return "pnpm";
|
|
30890
31414
|
if (declared?.startsWith("yarn@")) return "yarn";
|
|
30891
31415
|
if (declared?.startsWith("bun@")) return "bun";
|
|
30892
31416
|
if (declared?.startsWith("npm@")) return "npm";
|
|
30893
|
-
if (await fileExists2(
|
|
30894
|
-
if (await fileExists2(
|
|
30895
|
-
if (await fileExists2(
|
|
30896
|
-
if (await fileExists2(
|
|
30897
|
-
if (await fileExists2(
|
|
31417
|
+
if (await fileExists2(path67.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
|
|
31418
|
+
if (await fileExists2(path67.join(projectPath, "yarn.lock"))) return "yarn";
|
|
31419
|
+
if (await fileExists2(path67.join(projectPath, "bun.lockb"))) return "bun";
|
|
31420
|
+
if (await fileExists2(path67.join(projectPath, "bun.lock"))) return "bun";
|
|
31421
|
+
if (await fileExists2(path67.join(projectPath, "package-lock.json"))) return "npm";
|
|
30898
31422
|
return "npm";
|
|
30899
31423
|
}
|
|
30900
31424
|
function pmRun(pm, scriptName) {
|
|
@@ -30910,7 +31434,7 @@ function pmTest(pm) {
|
|
|
30910
31434
|
return "npm test";
|
|
30911
31435
|
}
|
|
30912
31436
|
async function detectProjectCommands(projectPath) {
|
|
30913
|
-
const pkgPath =
|
|
31437
|
+
const pkgPath = path67.join(projectPath, "package.json");
|
|
30914
31438
|
const pkg = await readJson(pkgPath, null);
|
|
30915
31439
|
if (pkg) {
|
|
30916
31440
|
const pm = await detectPackageManager(projectPath, pkg);
|
|
@@ -30927,27 +31451,27 @@ async function detectProjectCommands(projectPath) {
|
|
|
30927
31451
|
}
|
|
30928
31452
|
return result;
|
|
30929
31453
|
}
|
|
30930
|
-
if (await fileExists2(
|
|
31454
|
+
if (await fileExists2(path67.join(projectPath, "pytest.ini"))) {
|
|
30931
31455
|
return { stack: "python", test: { tool: "pytest", command: "pytest" } };
|
|
30932
31456
|
}
|
|
30933
|
-
const pyproject = await readFile(
|
|
31457
|
+
const pyproject = await readFile(path67.join(projectPath, "pyproject.toml"), "");
|
|
30934
31458
|
if (pyproject.includes("[tool.pytest") || pyproject.includes("pytest")) {
|
|
30935
31459
|
return { stack: "python", test: { tool: "pytest", command: "pytest" } };
|
|
30936
31460
|
}
|
|
30937
|
-
if (await fileExists2(
|
|
31461
|
+
if (await fileExists2(path67.join(projectPath, "Cargo.toml"))) {
|
|
30938
31462
|
return { stack: "rust", test: { tool: "cargo", command: "cargo test" } };
|
|
30939
31463
|
}
|
|
30940
|
-
if (await fileExists2(
|
|
31464
|
+
if (await fileExists2(path67.join(projectPath, "go.mod"))) {
|
|
30941
31465
|
return { stack: "go", test: { tool: "go", command: "go test ./..." } };
|
|
30942
31466
|
}
|
|
30943
31467
|
const files = await listFiles(projectPath);
|
|
30944
31468
|
if (files.some((f) => f.endsWith(".sln") || f.endsWith(".csproj") || f.endsWith(".fsproj"))) {
|
|
30945
31469
|
return { stack: "dotnet", test: { tool: "dotnet", command: "dotnet test" } };
|
|
30946
31470
|
}
|
|
30947
|
-
if (await fileExists2(
|
|
31471
|
+
if (await fileExists2(path67.join(projectPath, "pom.xml"))) {
|
|
30948
31472
|
return { stack: "java", test: { tool: "maven", command: "mvn test" } };
|
|
30949
31473
|
}
|
|
30950
|
-
if (await fileExists2(
|
|
31474
|
+
if (await fileExists2(path67.join(projectPath, "gradlew")) && (await fileExists2(path67.join(projectPath, "build.gradle")) || await fileExists2(path67.join(projectPath, "build.gradle.kts")))) {
|
|
30951
31475
|
return { stack: "java", test: { tool: "gradle", command: "./gradlew test" } };
|
|
30952
31476
|
}
|
|
30953
31477
|
return { stack: "unknown" };
|
|
@@ -30964,8 +31488,8 @@ var init_project_commands = __esm({
|
|
|
30964
31488
|
});
|
|
30965
31489
|
|
|
30966
31490
|
// core/workflow/workflow-preferences.ts
|
|
30967
|
-
import { exec as
|
|
30968
|
-
import { promisify as
|
|
31491
|
+
import { exec as exec18 } from "node:child_process";
|
|
31492
|
+
import { promisify as promisify19 } from "node:util";
|
|
30969
31493
|
import chalk18 from "chalk";
|
|
30970
31494
|
function prefKey(hook, command) {
|
|
30971
31495
|
return `workflow:${hook}_${command}`;
|
|
@@ -31108,7 +31632,7 @@ var init_workflow_preferences = __esm({
|
|
|
31108
31632
|
init_memory_system();
|
|
31109
31633
|
init_constants();
|
|
31110
31634
|
init_fs();
|
|
31111
|
-
execAsync12 =
|
|
31635
|
+
execAsync12 = promisify19(exec18);
|
|
31112
31636
|
sessionPreferences = /* @__PURE__ */ new Map();
|
|
31113
31637
|
oncePreferences = /* @__PURE__ */ new Map();
|
|
31114
31638
|
__name(prefKey, "prefKey");
|
|
@@ -31122,7 +31646,7 @@ var init_workflow_preferences = __esm({
|
|
|
31122
31646
|
});
|
|
31123
31647
|
|
|
31124
31648
|
// core/commands/shipping.ts
|
|
31125
|
-
import
|
|
31649
|
+
import path68 from "node:path";
|
|
31126
31650
|
var ShippingCommands;
|
|
31127
31651
|
var init_shipping = __esm({
|
|
31128
31652
|
"core/commands/shipping.ts"() {
|
|
@@ -31268,7 +31792,7 @@ ${result.stderr}`.trim();
|
|
|
31268
31792
|
*/
|
|
31269
31793
|
async _bumpVersion(projectPath) {
|
|
31270
31794
|
try {
|
|
31271
|
-
const pkgPath =
|
|
31795
|
+
const pkgPath = path68.join(projectPath, "package.json");
|
|
31272
31796
|
const pkg = await file_helper_exports.readJson(pkgPath, { version: "0.0.0" });
|
|
31273
31797
|
const oldVersion = pkg?.version || "0.0.0";
|
|
31274
31798
|
const [major, minor, patch] = oldVersion.split(".").map(Number);
|
|
@@ -31290,7 +31814,7 @@ ${result.stderr}`.trim();
|
|
|
31290
31814
|
*/
|
|
31291
31815
|
async _updateChangelog(feature, version, projectPath) {
|
|
31292
31816
|
try {
|
|
31293
|
-
const changelogPath =
|
|
31817
|
+
const changelogPath = path68.join(projectPath, "CHANGELOG.md");
|
|
31294
31818
|
const changelog = await file_helper_exports.readFile(changelogPath, "# Changelog\n\n");
|
|
31295
31819
|
const entry = `## [${version}] - ${date_helper_exports.formatDate(/* @__PURE__ */ new Date())}
|
|
31296
31820
|
|
|
@@ -31538,8 +32062,8 @@ var init_cache2 = __esm({
|
|
|
31538
32062
|
});
|
|
31539
32063
|
|
|
31540
32064
|
// core/utils/keychain.ts
|
|
31541
|
-
import { exec as
|
|
31542
|
-
import { promisify as
|
|
32065
|
+
import { exec as exec19 } from "node:child_process";
|
|
32066
|
+
import { promisify as promisify20 } from "node:util";
|
|
31543
32067
|
async function getCredential(key) {
|
|
31544
32068
|
if (process.platform !== "darwin") {
|
|
31545
32069
|
return getEnvFallback(key);
|
|
@@ -31566,7 +32090,7 @@ var init_keychain = __esm({
|
|
|
31566
32090
|
"core/utils/keychain.ts"() {
|
|
31567
32091
|
"use strict";
|
|
31568
32092
|
init_fs();
|
|
31569
|
-
execAsync13 =
|
|
32093
|
+
execAsync13 = promisify20(exec19);
|
|
31570
32094
|
SERVICE_NAME = "prjct-cli";
|
|
31571
32095
|
__name(getCredential, "getCredential");
|
|
31572
32096
|
__name(getEnvFallback, "getEnvFallback");
|
|
@@ -32334,11 +32858,11 @@ var init_linear = __esm({
|
|
|
32334
32858
|
});
|
|
32335
32859
|
|
|
32336
32860
|
// core/utils/project-credentials.ts
|
|
32337
|
-
import
|
|
32861
|
+
import fs59 from "node:fs/promises";
|
|
32338
32862
|
import os19 from "node:os";
|
|
32339
|
-
import
|
|
32863
|
+
import path69 from "node:path";
|
|
32340
32864
|
function getCredentialsPath(projectId) {
|
|
32341
|
-
return
|
|
32865
|
+
return path69.join(os19.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
|
|
32342
32866
|
}
|
|
32343
32867
|
async function getProjectCredentials(projectId) {
|
|
32344
32868
|
const credPath = getCredentialsPath(projectId);
|
|
@@ -32346,7 +32870,7 @@ async function getProjectCredentials(projectId) {
|
|
|
32346
32870
|
return {};
|
|
32347
32871
|
}
|
|
32348
32872
|
try {
|
|
32349
|
-
return JSON.parse(await
|
|
32873
|
+
return JSON.parse(await fs59.readFile(credPath, "utf-8"));
|
|
32350
32874
|
} catch (error) {
|
|
32351
32875
|
console.error("[project-credentials] Failed to read credentials:", getErrorMessage2(error));
|
|
32352
32876
|
return {};
|
|
@@ -33018,7 +33542,7 @@ var require_package = __commonJS({
|
|
|
33018
33542
|
"package.json"(exports, module) {
|
|
33019
33543
|
module.exports = {
|
|
33020
33544
|
name: "prjct-cli",
|
|
33021
|
-
version: "1.
|
|
33545
|
+
version: "1.17.0",
|
|
33022
33546
|
description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
|
|
33023
33547
|
main: "core/index.ts",
|
|
33024
33548
|
bin: {
|
|
@@ -33125,7 +33649,7 @@ var require_package = __commonJS({
|
|
|
33125
33649
|
// core/index.ts
|
|
33126
33650
|
var core_exports = {};
|
|
33127
33651
|
import os20 from "node:os";
|
|
33128
|
-
import
|
|
33652
|
+
import path70 from "node:path";
|
|
33129
33653
|
import chalk20 from "chalk";
|
|
33130
33654
|
async function main() {
|
|
33131
33655
|
const [commandName, ...rawArgs] = process.argv.slice(2);
|
|
@@ -33338,13 +33862,13 @@ function parseCommandArgs(_cmd, rawArgs) {
|
|
|
33338
33862
|
}
|
|
33339
33863
|
async function displayVersion(version) {
|
|
33340
33864
|
const detection = await detectAllProviders();
|
|
33341
|
-
const claudeCommandPath =
|
|
33342
|
-
const geminiCommandPath =
|
|
33865
|
+
const claudeCommandPath = path70.join(os20.homedir(), ".claude", "commands", "p.md");
|
|
33866
|
+
const geminiCommandPath = path70.join(os20.homedir(), ".gemini", "commands", "p.toml");
|
|
33343
33867
|
const [claudeConfigured, geminiConfigured, cursorConfigured, cursorExists] = await Promise.all([
|
|
33344
33868
|
fileExists(claudeCommandPath),
|
|
33345
33869
|
fileExists(geminiCommandPath),
|
|
33346
|
-
fileExists(
|
|
33347
|
-
fileExists(
|
|
33870
|
+
fileExists(path70.join(process.cwd(), ".cursor", "commands", "sync.md")),
|
|
33871
|
+
fileExists(path70.join(process.cwd(), ".cursor"))
|
|
33348
33872
|
]);
|
|
33349
33873
|
const antigravityDetection = await detectAntigravity();
|
|
33350
33874
|
console.log(`
|
|
@@ -33483,7 +34007,7 @@ init_ai_provider();
|
|
|
33483
34007
|
init_config_manager();
|
|
33484
34008
|
init_editors_config();
|
|
33485
34009
|
import os21 from "node:os";
|
|
33486
|
-
import
|
|
34010
|
+
import path71 from "node:path";
|
|
33487
34011
|
import chalk21 from "chalk";
|
|
33488
34012
|
|
|
33489
34013
|
// core/server/server.ts
|
|
@@ -34304,13 +34828,13 @@ async function checkRoutersInstalled() {
|
|
|
34304
34828
|
const home = os21.homedir();
|
|
34305
34829
|
const detection = await detectAllProviders();
|
|
34306
34830
|
if (detection.claude.installed) {
|
|
34307
|
-
const claudeRouter =
|
|
34831
|
+
const claudeRouter = path71.join(home, ".claude", "commands", "p.md");
|
|
34308
34832
|
if (!await fileExists(claudeRouter)) {
|
|
34309
34833
|
return false;
|
|
34310
34834
|
}
|
|
34311
34835
|
}
|
|
34312
34836
|
if (detection.gemini.installed) {
|
|
34313
|
-
const geminiRouter =
|
|
34837
|
+
const geminiRouter = path71.join(home, ".gemini", "commands", "p.toml");
|
|
34314
34838
|
if (!await fileExists(geminiRouter)) {
|
|
34315
34839
|
return false;
|
|
34316
34840
|
}
|
|
@@ -34451,7 +34975,7 @@ if (args[0] === "start" || args[0] === "setup") {
|
|
|
34451
34975
|
console.error('No prjct project found. Run "prjct init" first.');
|
|
34452
34976
|
process.exitCode = 1;
|
|
34453
34977
|
} else {
|
|
34454
|
-
const linearCliPath =
|
|
34978
|
+
const linearCliPath = path71.join(__dirname, "..", "core", "cli", "linear.ts");
|
|
34455
34979
|
const linearArgs = ["--project", projectId, ...args.slice(1)];
|
|
34456
34980
|
const child = spawn("bun", [linearCliPath, ...linearArgs], {
|
|
34457
34981
|
stdio: "inherit",
|
|
@@ -34478,12 +35002,12 @@ if (args[0] === "start" || args[0] === "setup") {
|
|
|
34478
35002
|
windsurfDetected,
|
|
34479
35003
|
windsurfConfigured
|
|
34480
35004
|
] = await Promise.all([
|
|
34481
|
-
fileExists(
|
|
34482
|
-
fileExists(
|
|
34483
|
-
fileExists(
|
|
34484
|
-
fileExists(
|
|
34485
|
-
fileExists(
|
|
34486
|
-
fileExists(
|
|
35005
|
+
fileExists(path71.join(home, ".claude", "commands", "p.md")),
|
|
35006
|
+
fileExists(path71.join(home, ".gemini", "commands", "p.toml")),
|
|
35007
|
+
fileExists(path71.join(cwd, ".cursor")),
|
|
35008
|
+
fileExists(path71.join(cwd, ".cursor", "rules", "prjct.mdc")),
|
|
35009
|
+
fileExists(path71.join(cwd, ".windsurf")),
|
|
35010
|
+
fileExists(path71.join(cwd, ".windsurf", "rules", "prjct.md"))
|
|
34487
35011
|
]);
|
|
34488
35012
|
console.log(`
|
|
34489
35013
|
${chalk21.cyan("p/")} prjct v${VERSION}
|
|
@@ -34522,7 +35046,7 @@ ${chalk21.dim("Run 'prjct init' to configure (Cursor/Windsurf IDE)")}
|
|
|
34522
35046
|
${chalk21.cyan("https://prjct.app")}
|
|
34523
35047
|
`);
|
|
34524
35048
|
} else {
|
|
34525
|
-
const configPath =
|
|
35049
|
+
const configPath = path71.join(os21.homedir(), ".prjct-cli", "config", "installed-editors.json");
|
|
34526
35050
|
const routersInstalled = await checkRoutersInstalled();
|
|
34527
35051
|
if (!await fileExists(configPath) || !routersInstalled) {
|
|
34528
35052
|
console.log(`
|