prjct-cli 1.19.0 → 1.21.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 +126 -2
- package/README.md +49 -0
- package/core/__tests__/storage/analysis-storage.test.ts +364 -0
- package/core/__tests__/utils/retry.test.ts +381 -0
- package/core/agentic/tool-registry.ts +40 -12
- package/core/commands/analysis.ts +96 -1
- package/core/commands/commands.ts +1 -1
- package/core/index.ts +5 -1
- package/core/schemas/analysis.ts +441 -0
- package/core/services/agent-generator.ts +35 -8
- package/core/services/agent-service.ts +17 -12
- package/core/storage/analysis-storage.ts +46 -1
- package/core/utils/retry.ts +318 -0
- package/dist/bin/prjct.mjs +1307 -655
- 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) => (path74) => {
|
|
20
|
+
var fn = map[path74];
|
|
21
21
|
if (fn) return fn();
|
|
22
|
-
throw new Error("Module not found in bundle: " +
|
|
22
|
+
throw new Error("Module not found in bundle: " + path74);
|
|
23
23
|
};
|
|
24
24
|
var __esm = (fn, res) => function __init() {
|
|
25
25
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -6600,11 +6600,11 @@ async function runSignaturesTool(args2, projectPath) {
|
|
|
6600
6600
|
}
|
|
6601
6601
|
};
|
|
6602
6602
|
}
|
|
6603
|
-
const
|
|
6604
|
-
const
|
|
6605
|
-
const fullPath =
|
|
6603
|
+
const fs62 = await import("node:fs/promises");
|
|
6604
|
+
const path74 = await import("node:path");
|
|
6605
|
+
const fullPath = path74.isAbsolute(filePath) ? filePath : path74.join(projectPath, filePath);
|
|
6606
6606
|
try {
|
|
6607
|
-
const stat = await
|
|
6607
|
+
const stat = await fs62.stat(fullPath);
|
|
6608
6608
|
if (stat.isDirectory()) {
|
|
6609
6609
|
const results = await extractDirectorySignatures(filePath, projectPath, {
|
|
6610
6610
|
recursive: args2.includes("--recursive") || args2.includes("-r")
|
|
@@ -6671,11 +6671,11 @@ async function runSummaryTool(args2, projectPath) {
|
|
|
6671
6671
|
}
|
|
6672
6672
|
};
|
|
6673
6673
|
}
|
|
6674
|
-
const
|
|
6675
|
-
const
|
|
6676
|
-
const fullPath =
|
|
6674
|
+
const fs62 = await import("node:fs/promises");
|
|
6675
|
+
const path74 = await import("node:path");
|
|
6676
|
+
const fullPath = path74.isAbsolute(targetPath) ? targetPath : path74.join(projectPath, targetPath);
|
|
6677
6677
|
try {
|
|
6678
|
-
const stat = await
|
|
6678
|
+
const stat = await fs62.stat(fullPath);
|
|
6679
6679
|
if (stat.isDirectory()) {
|
|
6680
6680
|
const results = await summarizeDirectory(targetPath, projectPath, {
|
|
6681
6681
|
recursive: args2.includes("--recursive") || args2.includes("-r")
|
|
@@ -9607,11 +9607,301 @@ var init_agents = __esm({
|
|
|
9607
9607
|
});
|
|
9608
9608
|
|
|
9609
9609
|
// core/schemas/analysis.ts
|
|
9610
|
+
import fs26 from "node:fs/promises";
|
|
9611
|
+
import path24 from "node:path";
|
|
9610
9612
|
import { z as z4 } from "zod";
|
|
9611
|
-
|
|
9613
|
+
async function verifyFrameworks(analysis2, projectPath) {
|
|
9614
|
+
const start = Date.now();
|
|
9615
|
+
if (analysis2.frameworks.length === 0) {
|
|
9616
|
+
return {
|
|
9617
|
+
name: "Framework verification",
|
|
9618
|
+
passed: true,
|
|
9619
|
+
output: "No frameworks declared (skipped)",
|
|
9620
|
+
durationMs: Date.now() - start
|
|
9621
|
+
};
|
|
9622
|
+
}
|
|
9623
|
+
try {
|
|
9624
|
+
const packagePath = path24.join(projectPath, "package.json");
|
|
9625
|
+
const content = await fs26.readFile(packagePath, "utf-8");
|
|
9626
|
+
const pkg = JSON.parse(content);
|
|
9627
|
+
const allDeps = {
|
|
9628
|
+
...pkg.dependencies,
|
|
9629
|
+
...pkg.devDependencies
|
|
9630
|
+
};
|
|
9631
|
+
const missing = [];
|
|
9632
|
+
const found = [];
|
|
9633
|
+
for (const framework of analysis2.frameworks) {
|
|
9634
|
+
const frameworkLower = framework.toLowerCase();
|
|
9635
|
+
const exists = Object.keys(allDeps).some((dep) => dep.toLowerCase().includes(frameworkLower));
|
|
9636
|
+
if (exists) {
|
|
9637
|
+
found.push(framework);
|
|
9638
|
+
} else {
|
|
9639
|
+
missing.push(framework);
|
|
9640
|
+
}
|
|
9641
|
+
}
|
|
9642
|
+
if (missing.length === 0) {
|
|
9643
|
+
return {
|
|
9644
|
+
name: "Framework verification",
|
|
9645
|
+
passed: true,
|
|
9646
|
+
output: `${found.length} framework(s) verified in dependencies`,
|
|
9647
|
+
durationMs: Date.now() - start
|
|
9648
|
+
};
|
|
9649
|
+
}
|
|
9650
|
+
return {
|
|
9651
|
+
name: "Framework verification",
|
|
9652
|
+
passed: false,
|
|
9653
|
+
error: `Frameworks not found in dependencies: ${missing.join(", ")}`,
|
|
9654
|
+
durationMs: Date.now() - start
|
|
9655
|
+
};
|
|
9656
|
+
} catch (error) {
|
|
9657
|
+
if (isNotFoundError(error)) {
|
|
9658
|
+
return {
|
|
9659
|
+
name: "Framework verification",
|
|
9660
|
+
passed: false,
|
|
9661
|
+
error: "package.json not found (cannot verify frameworks)",
|
|
9662
|
+
durationMs: Date.now() - start
|
|
9663
|
+
};
|
|
9664
|
+
}
|
|
9665
|
+
return {
|
|
9666
|
+
name: "Framework verification",
|
|
9667
|
+
passed: false,
|
|
9668
|
+
error: `Failed to read package.json: ${error instanceof Error ? error.message : "unknown error"}`,
|
|
9669
|
+
durationMs: Date.now() - start
|
|
9670
|
+
};
|
|
9671
|
+
}
|
|
9672
|
+
}
|
|
9673
|
+
async function verifyLanguages(analysis2, projectPath) {
|
|
9674
|
+
const start = Date.now();
|
|
9675
|
+
if (analysis2.languages.length === 0) {
|
|
9676
|
+
return {
|
|
9677
|
+
name: "Language verification",
|
|
9678
|
+
passed: true,
|
|
9679
|
+
output: "No languages declared (skipped)",
|
|
9680
|
+
durationMs: Date.now() - start
|
|
9681
|
+
};
|
|
9682
|
+
}
|
|
9683
|
+
try {
|
|
9684
|
+
const extensions = await getProjectExtensions(projectPath);
|
|
9685
|
+
const foundExtensions = new Set(extensions);
|
|
9686
|
+
const verified = [];
|
|
9687
|
+
const notFound = [];
|
|
9688
|
+
for (const language of analysis2.languages) {
|
|
9689
|
+
const expectedExts = LANGUAGE_EXTENSIONS[language];
|
|
9690
|
+
if (!expectedExts) {
|
|
9691
|
+
continue;
|
|
9692
|
+
}
|
|
9693
|
+
const hasMatchingFiles = expectedExts.some((ext) => foundExtensions.has(ext));
|
|
9694
|
+
if (hasMatchingFiles) {
|
|
9695
|
+
verified.push(language);
|
|
9696
|
+
} else {
|
|
9697
|
+
notFound.push(language);
|
|
9698
|
+
}
|
|
9699
|
+
}
|
|
9700
|
+
if (notFound.length === 0) {
|
|
9701
|
+
return {
|
|
9702
|
+
name: "Language verification",
|
|
9703
|
+
passed: true,
|
|
9704
|
+
output: `${verified.length} language(s) verified with matching files`,
|
|
9705
|
+
durationMs: Date.now() - start
|
|
9706
|
+
};
|
|
9707
|
+
}
|
|
9708
|
+
return {
|
|
9709
|
+
name: "Language verification",
|
|
9710
|
+
passed: false,
|
|
9711
|
+
error: `Languages without matching files: ${notFound.join(", ")}`,
|
|
9712
|
+
durationMs: Date.now() - start
|
|
9713
|
+
};
|
|
9714
|
+
} catch (error) {
|
|
9715
|
+
return {
|
|
9716
|
+
name: "Language verification",
|
|
9717
|
+
passed: false,
|
|
9718
|
+
error: `Failed to scan project files: ${error instanceof Error ? error.message : "unknown error"}`,
|
|
9719
|
+
durationMs: Date.now() - start
|
|
9720
|
+
};
|
|
9721
|
+
}
|
|
9722
|
+
}
|
|
9723
|
+
async function verifyPatternLocations(analysis2, projectPath) {
|
|
9724
|
+
const start = Date.now();
|
|
9725
|
+
const patternsWithLocations = analysis2.patterns.filter((p) => p.location);
|
|
9726
|
+
if (patternsWithLocations.length === 0) {
|
|
9727
|
+
return {
|
|
9728
|
+
name: "Pattern location verification",
|
|
9729
|
+
passed: true,
|
|
9730
|
+
output: "No pattern locations specified (skipped)",
|
|
9731
|
+
durationMs: Date.now() - start
|
|
9732
|
+
};
|
|
9733
|
+
}
|
|
9734
|
+
const missing = [];
|
|
9735
|
+
const verified = [];
|
|
9736
|
+
for (const pattern of patternsWithLocations) {
|
|
9737
|
+
const location = pattern.location;
|
|
9738
|
+
const filePath = path24.join(projectPath, location);
|
|
9739
|
+
try {
|
|
9740
|
+
await fs26.access(filePath);
|
|
9741
|
+
verified.push(location);
|
|
9742
|
+
} catch {
|
|
9743
|
+
missing.push(`${pattern.name} (${location})`);
|
|
9744
|
+
}
|
|
9745
|
+
}
|
|
9746
|
+
if (missing.length === 0) {
|
|
9747
|
+
return {
|
|
9748
|
+
name: "Pattern location verification",
|
|
9749
|
+
passed: true,
|
|
9750
|
+
output: `${verified.length} pattern location(s) verified`,
|
|
9751
|
+
durationMs: Date.now() - start
|
|
9752
|
+
};
|
|
9753
|
+
}
|
|
9754
|
+
return {
|
|
9755
|
+
name: "Pattern location verification",
|
|
9756
|
+
passed: false,
|
|
9757
|
+
error: `Pattern locations not found: ${missing.join(", ")}`,
|
|
9758
|
+
durationMs: Date.now() - start
|
|
9759
|
+
};
|
|
9760
|
+
}
|
|
9761
|
+
async function verifyFileCount(analysis2, projectPath) {
|
|
9762
|
+
const start = Date.now();
|
|
9763
|
+
try {
|
|
9764
|
+
const actualCount = await countProjectFiles(projectPath);
|
|
9765
|
+
const declared = analysis2.fileCount;
|
|
9766
|
+
const tolerance = 0.1;
|
|
9767
|
+
const diff = Math.abs(actualCount - declared);
|
|
9768
|
+
const allowedDiff = declared * tolerance;
|
|
9769
|
+
if (diff <= allowedDiff) {
|
|
9770
|
+
return {
|
|
9771
|
+
name: "File count verification",
|
|
9772
|
+
passed: true,
|
|
9773
|
+
output: `File count accurate (declared: ${declared}, actual: ${actualCount})`,
|
|
9774
|
+
durationMs: Date.now() - start
|
|
9775
|
+
};
|
|
9776
|
+
}
|
|
9777
|
+
return {
|
|
9778
|
+
name: "File count verification",
|
|
9779
|
+
passed: false,
|
|
9780
|
+
error: `File count mismatch: declared ${declared}, actual ${actualCount} (diff: ${diff})`,
|
|
9781
|
+
durationMs: Date.now() - start
|
|
9782
|
+
};
|
|
9783
|
+
} catch (error) {
|
|
9784
|
+
return {
|
|
9785
|
+
name: "File count verification",
|
|
9786
|
+
passed: false,
|
|
9787
|
+
error: `Failed to count files: ${error instanceof Error ? error.message : "unknown error"}`,
|
|
9788
|
+
durationMs: Date.now() - start
|
|
9789
|
+
};
|
|
9790
|
+
}
|
|
9791
|
+
}
|
|
9792
|
+
async function verifyAntiPatternFiles(analysis2, projectPath) {
|
|
9793
|
+
const start = Date.now();
|
|
9794
|
+
if (analysis2.antiPatterns.length === 0) {
|
|
9795
|
+
return {
|
|
9796
|
+
name: "Anti-pattern file verification",
|
|
9797
|
+
passed: true,
|
|
9798
|
+
output: "No anti-patterns declared (skipped)",
|
|
9799
|
+
durationMs: Date.now() - start
|
|
9800
|
+
};
|
|
9801
|
+
}
|
|
9802
|
+
const missing = [];
|
|
9803
|
+
const verified = [];
|
|
9804
|
+
for (const antiPattern of analysis2.antiPatterns) {
|
|
9805
|
+
const filePath = path24.join(projectPath, antiPattern.file);
|
|
9806
|
+
try {
|
|
9807
|
+
await fs26.access(filePath);
|
|
9808
|
+
verified.push(antiPattern.file);
|
|
9809
|
+
} catch {
|
|
9810
|
+
missing.push(`${antiPattern.issue} (${antiPattern.file})`);
|
|
9811
|
+
}
|
|
9812
|
+
}
|
|
9813
|
+
if (missing.length === 0) {
|
|
9814
|
+
return {
|
|
9815
|
+
name: "Anti-pattern file verification",
|
|
9816
|
+
passed: true,
|
|
9817
|
+
output: `${verified.length} anti-pattern file(s) verified`,
|
|
9818
|
+
durationMs: Date.now() - start
|
|
9819
|
+
};
|
|
9820
|
+
}
|
|
9821
|
+
return {
|
|
9822
|
+
name: "Anti-pattern file verification",
|
|
9823
|
+
passed: false,
|
|
9824
|
+
error: `Anti-pattern files not found: ${missing.join(", ")}`,
|
|
9825
|
+
durationMs: Date.now() - start
|
|
9826
|
+
};
|
|
9827
|
+
}
|
|
9828
|
+
async function semanticVerify(analysis2, projectPath) {
|
|
9829
|
+
const totalStart = Date.now();
|
|
9830
|
+
const checks = await Promise.all([
|
|
9831
|
+
verifyFrameworks(analysis2, projectPath),
|
|
9832
|
+
verifyLanguages(analysis2, projectPath),
|
|
9833
|
+
verifyPatternLocations(analysis2, projectPath),
|
|
9834
|
+
verifyFileCount(analysis2, projectPath),
|
|
9835
|
+
verifyAntiPatternFiles(analysis2, projectPath)
|
|
9836
|
+
]);
|
|
9837
|
+
const failedCount = checks.filter((c) => !c.passed).length;
|
|
9838
|
+
const passedCount = checks.filter((c) => c.passed).length;
|
|
9839
|
+
return {
|
|
9840
|
+
passed: failedCount === 0,
|
|
9841
|
+
checks,
|
|
9842
|
+
totalMs: Date.now() - totalStart,
|
|
9843
|
+
failedCount,
|
|
9844
|
+
passedCount
|
|
9845
|
+
};
|
|
9846
|
+
}
|
|
9847
|
+
async function getProjectExtensions(projectPath) {
|
|
9848
|
+
const extensions = /* @__PURE__ */ new Set();
|
|
9849
|
+
const ignorePatterns = [/node_modules/, /\.git/, /dist/, /build/, /\.next/, /\.turbo/, /coverage/];
|
|
9850
|
+
async function scanDir(dir) {
|
|
9851
|
+
try {
|
|
9852
|
+
const entries = await fs26.readdir(dir, { withFileTypes: true });
|
|
9853
|
+
for (const entry of entries) {
|
|
9854
|
+
const fullPath = path24.join(dir, entry.name);
|
|
9855
|
+
const relativePath = path24.relative(projectPath, fullPath);
|
|
9856
|
+
if (ignorePatterns.some((pattern) => pattern.test(relativePath))) {
|
|
9857
|
+
continue;
|
|
9858
|
+
}
|
|
9859
|
+
if (entry.isDirectory()) {
|
|
9860
|
+
await scanDir(fullPath);
|
|
9861
|
+
} else if (entry.isFile()) {
|
|
9862
|
+
const ext = path24.extname(entry.name);
|
|
9863
|
+
if (ext) {
|
|
9864
|
+
extensions.add(ext);
|
|
9865
|
+
}
|
|
9866
|
+
}
|
|
9867
|
+
}
|
|
9868
|
+
} catch {
|
|
9869
|
+
}
|
|
9870
|
+
}
|
|
9871
|
+
__name(scanDir, "scanDir");
|
|
9872
|
+
await scanDir(projectPath);
|
|
9873
|
+
return Array.from(extensions);
|
|
9874
|
+
}
|
|
9875
|
+
async function countProjectFiles(projectPath) {
|
|
9876
|
+
let count = 0;
|
|
9877
|
+
const ignorePatterns = [/node_modules/, /\.git/, /dist/, /build/, /\.next/, /\.turbo/, /coverage/];
|
|
9878
|
+
async function scanDir(dir) {
|
|
9879
|
+
try {
|
|
9880
|
+
const entries = await fs26.readdir(dir, { withFileTypes: true });
|
|
9881
|
+
for (const entry of entries) {
|
|
9882
|
+
const fullPath = path24.join(dir, entry.name);
|
|
9883
|
+
const relativePath = path24.relative(projectPath, fullPath);
|
|
9884
|
+
if (ignorePatterns.some((pattern) => pattern.test(relativePath))) {
|
|
9885
|
+
continue;
|
|
9886
|
+
}
|
|
9887
|
+
if (entry.isDirectory()) {
|
|
9888
|
+
await scanDir(fullPath);
|
|
9889
|
+
} else if (entry.isFile()) {
|
|
9890
|
+
count++;
|
|
9891
|
+
}
|
|
9892
|
+
}
|
|
9893
|
+
} catch {
|
|
9894
|
+
}
|
|
9895
|
+
}
|
|
9896
|
+
__name(scanDir, "scanDir");
|
|
9897
|
+
await scanDir(projectPath);
|
|
9898
|
+
return count;
|
|
9899
|
+
}
|
|
9900
|
+
var AnalysisStatusSchema, CodePatternSchema, AntiPatternSchema, AnalysisItemSchema, DEFAULT_ANALYSIS, LANGUAGE_EXTENSIONS;
|
|
9612
9901
|
var init_analysis = __esm({
|
|
9613
9902
|
"core/schemas/analysis.ts"() {
|
|
9614
9903
|
"use strict";
|
|
9904
|
+
init_fs();
|
|
9615
9905
|
init_model();
|
|
9616
9906
|
AnalysisStatusSchema = z4.enum(["draft", "verified", "sealed"]);
|
|
9617
9907
|
CodePatternSchema = z4.object({
|
|
@@ -9663,6 +9953,31 @@ var init_analysis = __esm({
|
|
|
9663
9953
|
analyzedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9664
9954
|
status: "draft"
|
|
9665
9955
|
};
|
|
9956
|
+
LANGUAGE_EXTENSIONS = {
|
|
9957
|
+
TypeScript: [".ts", ".tsx", ".mts", ".cts"],
|
|
9958
|
+
JavaScript: [".js", ".jsx", ".mjs", ".cjs"],
|
|
9959
|
+
Python: [".py", ".pyw"],
|
|
9960
|
+
Java: [".java"],
|
|
9961
|
+
Go: [".go"],
|
|
9962
|
+
Rust: [".rs"],
|
|
9963
|
+
Ruby: [".rb"],
|
|
9964
|
+
PHP: [".php"],
|
|
9965
|
+
Swift: [".swift"],
|
|
9966
|
+
Kotlin: [".kt", ".kts"],
|
|
9967
|
+
"C++": [".cpp", ".cc", ".cxx", ".hpp", ".h"],
|
|
9968
|
+
C: [".c", ".h"],
|
|
9969
|
+
"C#": [".cs"],
|
|
9970
|
+
Elixir: [".ex", ".exs"],
|
|
9971
|
+
Scala: [".scala"]
|
|
9972
|
+
};
|
|
9973
|
+
__name(verifyFrameworks, "verifyFrameworks");
|
|
9974
|
+
__name(verifyLanguages, "verifyLanguages");
|
|
9975
|
+
__name(verifyPatternLocations, "verifyPatternLocations");
|
|
9976
|
+
__name(verifyFileCount, "verifyFileCount");
|
|
9977
|
+
__name(verifyAntiPatternFiles, "verifyAntiPatternFiles");
|
|
9978
|
+
__name(semanticVerify, "semanticVerify");
|
|
9979
|
+
__name(getProjectExtensions, "getProjectExtensions");
|
|
9980
|
+
__name(countProjectFiles, "countProjectFiles");
|
|
9666
9981
|
}
|
|
9667
9982
|
});
|
|
9668
9983
|
|
|
@@ -10960,8 +11275,8 @@ var init_memory = __esm({
|
|
|
10960
11275
|
});
|
|
10961
11276
|
|
|
10962
11277
|
// core/agentic/memory-system.ts
|
|
10963
|
-
import
|
|
10964
|
-
import
|
|
11278
|
+
import fs27 from "node:fs/promises";
|
|
11279
|
+
import path25 from "node:path";
|
|
10965
11280
|
function resolveCanonicalDomains(domain) {
|
|
10966
11281
|
if (KNOWN_DOMAINS.includes(domain)) {
|
|
10967
11282
|
return [domain];
|
|
@@ -11130,12 +11445,12 @@ var init_memory_system = __esm({
|
|
|
11130
11445
|
* (e.g., `~/.prjct-cli/projects/{id}/memory/patterns.json`)
|
|
11131
11446
|
*/
|
|
11132
11447
|
getPath(projectId) {
|
|
11133
|
-
const basePath =
|
|
11448
|
+
const basePath = path25.join(path_manager_default.getGlobalProjectPath(projectId), "memory");
|
|
11134
11449
|
const subdir = this.getSubdirectory();
|
|
11135
11450
|
if (subdir) {
|
|
11136
|
-
return
|
|
11451
|
+
return path25.join(basePath, subdir, this.getFilename());
|
|
11137
11452
|
}
|
|
11138
|
-
return
|
|
11453
|
+
return path25.join(basePath, this.getFilename());
|
|
11139
11454
|
}
|
|
11140
11455
|
/**
|
|
11141
11456
|
* Load data from disk with project-scoped caching.
|
|
@@ -11159,7 +11474,7 @@ var init_memory_system = __esm({
|
|
|
11159
11474
|
}
|
|
11160
11475
|
const filePath = this.getPath(projectId);
|
|
11161
11476
|
try {
|
|
11162
|
-
const content = await
|
|
11477
|
+
const content = await fs27.readFile(filePath, "utf-8");
|
|
11163
11478
|
this._data = JSON.parse(content);
|
|
11164
11479
|
this.afterLoad(this._data);
|
|
11165
11480
|
} catch (error) {
|
|
@@ -11195,8 +11510,8 @@ var init_memory_system = __esm({
|
|
|
11195
11510
|
async save(projectId) {
|
|
11196
11511
|
if (!this._data) return;
|
|
11197
11512
|
const filePath = this.getPath(projectId);
|
|
11198
|
-
await
|
|
11199
|
-
await
|
|
11513
|
+
await fs27.mkdir(path25.dirname(filePath), { recursive: true });
|
|
11514
|
+
await fs27.writeFile(filePath, JSON.stringify(this._data, null, 2), "utf-8");
|
|
11200
11515
|
}
|
|
11201
11516
|
/**
|
|
11202
11517
|
* Access the cached data without triggering a disk read.
|
|
@@ -11285,7 +11600,7 @@ var init_memory_system = __esm({
|
|
|
11285
11600
|
const now = /* @__PURE__ */ new Date();
|
|
11286
11601
|
const yearMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
|
|
11287
11602
|
const day = getTodayKey();
|
|
11288
|
-
return
|
|
11603
|
+
return path25.join(
|
|
11289
11604
|
path_manager_default.getGlobalProjectPath(projectId),
|
|
11290
11605
|
"memory",
|
|
11291
11606
|
"sessions",
|
|
@@ -11295,7 +11610,7 @@ var init_memory_system = __esm({
|
|
|
11295
11610
|
}
|
|
11296
11611
|
async appendHistory(projectId, entry) {
|
|
11297
11612
|
const sessionPath = this._getSessionPath(projectId);
|
|
11298
|
-
await ensureDir(
|
|
11613
|
+
await ensureDir(path25.dirname(sessionPath));
|
|
11299
11614
|
const logEntry = {
|
|
11300
11615
|
ts: getTimestamp(),
|
|
11301
11616
|
...entry,
|
|
@@ -11473,8 +11788,8 @@ var init_memory_system = __esm({
|
|
|
11473
11788
|
};
|
|
11474
11789
|
}
|
|
11475
11790
|
_getArchivePath(projectId) {
|
|
11476
|
-
const basePath =
|
|
11477
|
-
return
|
|
11791
|
+
const basePath = path25.join(path_manager_default.getGlobalProjectPath(projectId), "memory");
|
|
11792
|
+
return path25.join(basePath, "patterns-archive.json");
|
|
11478
11793
|
}
|
|
11479
11794
|
async archiveStaleDecisions(projectId) {
|
|
11480
11795
|
const patterns = await this.load(projectId);
|
|
@@ -11491,7 +11806,7 @@ var init_memory_system = __esm({
|
|
|
11491
11806
|
const archivePath = this._getArchivePath(projectId);
|
|
11492
11807
|
let archive = {};
|
|
11493
11808
|
try {
|
|
11494
|
-
const content = await
|
|
11809
|
+
const content = await fs27.readFile(archivePath, "utf-8");
|
|
11495
11810
|
archive = JSON.parse(content);
|
|
11496
11811
|
} catch (error) {
|
|
11497
11812
|
if (!isNotFoundError(error)) throw error;
|
|
@@ -11500,8 +11815,8 @@ var init_memory_system = __esm({
|
|
|
11500
11815
|
archive[key] = patterns.decisions[key];
|
|
11501
11816
|
delete patterns.decisions[key];
|
|
11502
11817
|
}
|
|
11503
|
-
await
|
|
11504
|
-
await
|
|
11818
|
+
await fs27.mkdir(path25.dirname(archivePath), { recursive: true });
|
|
11819
|
+
await fs27.writeFile(archivePath, JSON.stringify(archive, null, 2), "utf-8");
|
|
11505
11820
|
await this.save(projectId);
|
|
11506
11821
|
return staleKeys.length;
|
|
11507
11822
|
}
|
|
@@ -12349,7 +12664,7 @@ var init_velocity2 = __esm({
|
|
|
12349
12664
|
});
|
|
12350
12665
|
|
|
12351
12666
|
// core/outcomes/recorder.ts
|
|
12352
|
-
import
|
|
12667
|
+
import path26 from "node:path";
|
|
12353
12668
|
var OUTCOMES_DIR, OUTCOMES_FILE, OutcomeRecorder, outcomeRecorder, recorder_default;
|
|
12354
12669
|
var init_recorder = __esm({
|
|
12355
12670
|
"core/outcomes/recorder.ts"() {
|
|
@@ -12368,13 +12683,13 @@ var init_recorder = __esm({
|
|
|
12368
12683
|
*/
|
|
12369
12684
|
getOutcomesDir(projectId) {
|
|
12370
12685
|
const globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
12371
|
-
return
|
|
12686
|
+
return path26.join(globalPath, OUTCOMES_DIR);
|
|
12372
12687
|
}
|
|
12373
12688
|
/**
|
|
12374
12689
|
* Get outcomes file path for a project.
|
|
12375
12690
|
*/
|
|
12376
12691
|
getOutcomesPath(projectId) {
|
|
12377
|
-
return
|
|
12692
|
+
return path26.join(this.getOutcomesDir(projectId), OUTCOMES_FILE);
|
|
12378
12693
|
}
|
|
12379
12694
|
/**
|
|
12380
12695
|
* Record an outcome.
|
|
@@ -12385,7 +12700,7 @@ var init_recorder = __esm({
|
|
|
12385
12700
|
id: generateUUID()
|
|
12386
12701
|
};
|
|
12387
12702
|
const outcomesPath = this.getOutcomesPath(projectId);
|
|
12388
|
-
await ensureDir(
|
|
12703
|
+
await ensureDir(path26.dirname(outcomesPath));
|
|
12389
12704
|
await appendLine(outcomesPath, JSON.stringify(outcome));
|
|
12390
12705
|
return outcome;
|
|
12391
12706
|
}
|
|
@@ -12721,6 +13036,36 @@ var init_analysis_storage = __esm({
|
|
|
12721
13036
|
message: `Signature mismatch. Expected ${expected}, got ${data.sealed.signature}. Analysis may have been modified.`
|
|
12722
13037
|
};
|
|
12723
13038
|
}
|
|
13039
|
+
/**
|
|
13040
|
+
* Perform semantic verification on analysis results (PRJ-270).
|
|
13041
|
+
* Validates that analysis data matches actual project state:
|
|
13042
|
+
* - Frameworks exist in package.json
|
|
13043
|
+
* - Languages match file extensions
|
|
13044
|
+
* - Pattern locations reference real files
|
|
13045
|
+
* - File count is accurate
|
|
13046
|
+
* - Anti-pattern files exist
|
|
13047
|
+
*/
|
|
13048
|
+
async semanticVerify(projectId, projectPath) {
|
|
13049
|
+
const data = await this.read(projectId);
|
|
13050
|
+
const analysis2 = data.sealed ?? data.draft;
|
|
13051
|
+
if (!analysis2) {
|
|
13052
|
+
return {
|
|
13053
|
+
passed: false,
|
|
13054
|
+
checks: [
|
|
13055
|
+
{
|
|
13056
|
+
name: "Analysis availability",
|
|
13057
|
+
passed: false,
|
|
13058
|
+
error: "No analysis available. Run `p. sync` to generate.",
|
|
13059
|
+
durationMs: 0
|
|
13060
|
+
}
|
|
13061
|
+
],
|
|
13062
|
+
totalMs: 0,
|
|
13063
|
+
failedCount: 1,
|
|
13064
|
+
passedCount: 0
|
|
13065
|
+
};
|
|
13066
|
+
}
|
|
13067
|
+
return await semanticVerify(analysis2, projectPath);
|
|
13068
|
+
}
|
|
12724
13069
|
// ===========================================================================
|
|
12725
13070
|
// Private Helpers
|
|
12726
13071
|
// ===========================================================================
|
|
@@ -13138,8 +13483,8 @@ var init_ideas_storage = __esm({
|
|
|
13138
13483
|
|
|
13139
13484
|
// core/storage/index-storage.ts
|
|
13140
13485
|
import crypto4 from "node:crypto";
|
|
13141
|
-
import
|
|
13142
|
-
import
|
|
13486
|
+
import fs28 from "node:fs/promises";
|
|
13487
|
+
import path27 from "node:path";
|
|
13143
13488
|
function getDefaultChecksums() {
|
|
13144
13489
|
return {
|
|
13145
13490
|
version: INDEX_VERSION,
|
|
@@ -13165,14 +13510,14 @@ var init_index_storage = __esm({
|
|
|
13165
13510
|
* Get the index directory path for a project
|
|
13166
13511
|
*/
|
|
13167
13512
|
getIndexPath(projectId) {
|
|
13168
|
-
return
|
|
13513
|
+
return path27.join(path_manager_default.getGlobalProjectPath(projectId), "index");
|
|
13169
13514
|
}
|
|
13170
13515
|
/**
|
|
13171
13516
|
* Ensure index directory exists
|
|
13172
13517
|
*/
|
|
13173
13518
|
async ensureIndexDir(projectId) {
|
|
13174
13519
|
const indexPath = this.getIndexPath(projectId);
|
|
13175
|
-
await
|
|
13520
|
+
await fs28.mkdir(indexPath, { recursive: true });
|
|
13176
13521
|
return indexPath;
|
|
13177
13522
|
}
|
|
13178
13523
|
// ==========================================================================
|
|
@@ -13232,7 +13577,7 @@ var init_index_storage = __esm({
|
|
|
13232
13577
|
*/
|
|
13233
13578
|
async calculateChecksum(filePath) {
|
|
13234
13579
|
try {
|
|
13235
|
-
const content = await
|
|
13580
|
+
const content = await fs28.readFile(filePath);
|
|
13236
13581
|
return crypto4.createHash("md5").update(content).digest("hex");
|
|
13237
13582
|
} catch {
|
|
13238
13583
|
return "";
|
|
@@ -13301,8 +13646,8 @@ var init_index_storage = __esm({
|
|
|
13301
13646
|
}
|
|
13302
13647
|
const indexPath = this.getIndexPath(projectId);
|
|
13303
13648
|
try {
|
|
13304
|
-
const files = await
|
|
13305
|
-
await Promise.all(files.map((file) =>
|
|
13649
|
+
const files = await fs28.readdir(indexPath);
|
|
13650
|
+
await Promise.all(files.map((file) => fs28.unlink(path27.join(indexPath, file))));
|
|
13306
13651
|
} catch (error) {
|
|
13307
13652
|
if (!isNotFoundError(error)) {
|
|
13308
13653
|
throw error;
|
|
@@ -13427,8 +13772,8 @@ var init_index_storage = __esm({
|
|
|
13427
13772
|
});
|
|
13428
13773
|
|
|
13429
13774
|
// core/storage/migrate-json.ts
|
|
13430
|
-
import
|
|
13431
|
-
import
|
|
13775
|
+
import fs29 from "node:fs/promises";
|
|
13776
|
+
import path28 from "node:path";
|
|
13432
13777
|
async function migrateJsonToSqlite(projectId) {
|
|
13433
13778
|
const start = Date.now();
|
|
13434
13779
|
const result = {
|
|
@@ -13446,13 +13791,13 @@ async function migrateJsonToSqlite(projectId) {
|
|
|
13446
13791
|
return result;
|
|
13447
13792
|
}
|
|
13448
13793
|
const globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
13449
|
-
const storagePath =
|
|
13450
|
-
const indexPath =
|
|
13451
|
-
const memoryPath =
|
|
13794
|
+
const storagePath = path28.join(globalPath, "storage");
|
|
13795
|
+
const indexPath = path28.join(globalPath, "index");
|
|
13796
|
+
const memoryPath = path28.join(globalPath, "memory");
|
|
13452
13797
|
result.backupDir = await createBackup2(storagePath, indexPath, memoryPath);
|
|
13453
13798
|
prjctDb.getDb(projectId);
|
|
13454
13799
|
for (const { filename, key } of STORAGE_FILES) {
|
|
13455
|
-
const filePath =
|
|
13800
|
+
const filePath = path28.join(storagePath, filename);
|
|
13456
13801
|
const data = await readJsonSafe(filePath);
|
|
13457
13802
|
if (data === null) {
|
|
13458
13803
|
result.skippedFiles.push(filename);
|
|
@@ -13467,7 +13812,7 @@ async function migrateJsonToSqlite(projectId) {
|
|
|
13467
13812
|
}
|
|
13468
13813
|
}
|
|
13469
13814
|
for (const { filename, key } of INDEX_FILES) {
|
|
13470
|
-
const filePath =
|
|
13815
|
+
const filePath = path28.join(indexPath, filename);
|
|
13471
13816
|
const data = await readJsonSafe(filePath);
|
|
13472
13817
|
if (data === null) {
|
|
13473
13818
|
result.skippedFiles.push(`index/${filename}`);
|
|
@@ -13504,28 +13849,28 @@ async function migrateJsonToSqlite(projectId) {
|
|
|
13504
13849
|
}
|
|
13505
13850
|
}
|
|
13506
13851
|
async function createBackup2(storagePath, indexPath, memoryPath) {
|
|
13507
|
-
const backupDir =
|
|
13508
|
-
await
|
|
13509
|
-
await
|
|
13510
|
-
await
|
|
13852
|
+
const backupDir = path28.join(storagePath, "backup");
|
|
13853
|
+
await fs29.mkdir(backupDir, { recursive: true });
|
|
13854
|
+
await fs29.mkdir(path28.join(backupDir, "index"), { recursive: true });
|
|
13855
|
+
await fs29.mkdir(path28.join(backupDir, "memory"), { recursive: true });
|
|
13511
13856
|
await copyFiles(
|
|
13512
13857
|
storagePath,
|
|
13513
13858
|
backupDir,
|
|
13514
13859
|
(name) => name.endsWith(".json") || name.endsWith(".jsonl")
|
|
13515
13860
|
);
|
|
13516
|
-
await copyFiles(indexPath,
|
|
13517
|
-
await copyFiles(memoryPath,
|
|
13861
|
+
await copyFiles(indexPath, path28.join(backupDir, "index"));
|
|
13862
|
+
await copyFiles(memoryPath, path28.join(backupDir, "memory"));
|
|
13518
13863
|
return backupDir;
|
|
13519
13864
|
}
|
|
13520
13865
|
async function copyFiles(srcDir, destDir, filter) {
|
|
13521
13866
|
try {
|
|
13522
|
-
const entries = await
|
|
13867
|
+
const entries = await fs29.readdir(srcDir, { withFileTypes: true });
|
|
13523
13868
|
for (const entry of entries) {
|
|
13524
13869
|
if (!entry.isFile()) continue;
|
|
13525
13870
|
if (filter && !filter(entry.name)) continue;
|
|
13526
|
-
const src =
|
|
13527
|
-
const dest =
|
|
13528
|
-
await
|
|
13871
|
+
const src = path28.join(srcDir, entry.name);
|
|
13872
|
+
const dest = path28.join(destDir, entry.name);
|
|
13873
|
+
await fs29.copyFile(src, dest);
|
|
13529
13874
|
}
|
|
13530
13875
|
} catch (err) {
|
|
13531
13876
|
if (!isNotFoundError(err)) throw err;
|
|
@@ -13755,7 +14100,7 @@ function populateCategoriesIndex(projectId, cache2) {
|
|
|
13755
14100
|
}
|
|
13756
14101
|
}
|
|
13757
14102
|
async function migrateChecksums(projectId, indexPath, result) {
|
|
13758
|
-
const filePath =
|
|
14103
|
+
const filePath = path28.join(indexPath, "checksums.json");
|
|
13759
14104
|
const data = await readJsonSafe(filePath);
|
|
13760
14105
|
if (data === null) {
|
|
13761
14106
|
result.skippedFiles.push("index/checksums.json");
|
|
@@ -13777,7 +14122,7 @@ async function migrateChecksums(projectId, indexPath, result) {
|
|
|
13777
14122
|
}
|
|
13778
14123
|
}
|
|
13779
14124
|
async function migrateFileScores(projectId, indexPath, result) {
|
|
13780
|
-
const filePath =
|
|
14125
|
+
const filePath = path28.join(indexPath, "file-scores.json");
|
|
13781
14126
|
const data = await readJsonSafe(filePath);
|
|
13782
14127
|
if (data === null) {
|
|
13783
14128
|
result.skippedFiles.push("index/file-scores.json");
|
|
@@ -13812,9 +14157,9 @@ async function migrateFileScores(projectId, indexPath, result) {
|
|
|
13812
14157
|
}
|
|
13813
14158
|
}
|
|
13814
14159
|
async function migrateEventsJsonl(projectId, memoryPath, result) {
|
|
13815
|
-
const filePath =
|
|
14160
|
+
const filePath = path28.join(memoryPath, "events.jsonl");
|
|
13816
14161
|
try {
|
|
13817
|
-
const content = await
|
|
14162
|
+
const content = await fs29.readFile(filePath, "utf-8");
|
|
13818
14163
|
const lines = content.split("\n").filter((line) => line.trim());
|
|
13819
14164
|
if (lines.length === 0) {
|
|
13820
14165
|
result.skippedFiles.push("memory/events.jsonl");
|
|
@@ -13846,9 +14191,9 @@ async function migrateEventsJsonl(projectId, memoryPath, result) {
|
|
|
13846
14191
|
}
|
|
13847
14192
|
}
|
|
13848
14193
|
async function migrateLearningsJsonl(projectId, memoryPath, result) {
|
|
13849
|
-
const filePath =
|
|
14194
|
+
const filePath = path28.join(memoryPath, "learnings.jsonl");
|
|
13850
14195
|
try {
|
|
13851
|
-
const content = await
|
|
14196
|
+
const content = await fs29.readFile(filePath, "utf-8");
|
|
13852
14197
|
const lines = content.split("\n").filter((line) => line.trim());
|
|
13853
14198
|
if (lines.length === 0) {
|
|
13854
14199
|
result.skippedFiles.push("memory/learnings.jsonl");
|
|
@@ -13882,7 +14227,7 @@ async function migrateLearningsJsonl(projectId, memoryPath, result) {
|
|
|
13882
14227
|
async function cleanupJsonFiles(storagePath, indexPath, memoryPath, result) {
|
|
13883
14228
|
const deleteFile2 = /* @__PURE__ */ __name(async (filePath, label) => {
|
|
13884
14229
|
try {
|
|
13885
|
-
await
|
|
14230
|
+
await fs29.unlink(filePath);
|
|
13886
14231
|
} catch (err) {
|
|
13887
14232
|
if (!isNotFoundError(err)) {
|
|
13888
14233
|
result.errors.push({ file: label, error: `cleanup: ${String(err)}` });
|
|
@@ -13890,7 +14235,7 @@ async function cleanupJsonFiles(storagePath, indexPath, memoryPath, result) {
|
|
|
13890
14235
|
}
|
|
13891
14236
|
}, "deleteFile");
|
|
13892
14237
|
for (const { filename } of STORAGE_FILES) {
|
|
13893
|
-
await deleteFile2(
|
|
14238
|
+
await deleteFile2(path28.join(storagePath, filename), `cleanup:${filename}`);
|
|
13894
14239
|
}
|
|
13895
14240
|
const indexFiles = [
|
|
13896
14241
|
"project-index.json",
|
|
@@ -13900,14 +14245,14 @@ async function cleanupJsonFiles(storagePath, indexPath, memoryPath, result) {
|
|
|
13900
14245
|
"file-scores.json"
|
|
13901
14246
|
];
|
|
13902
14247
|
for (const filename of indexFiles) {
|
|
13903
|
-
await deleteFile2(
|
|
14248
|
+
await deleteFile2(path28.join(indexPath, filename), `cleanup:index/${filename}`);
|
|
13904
14249
|
}
|
|
13905
|
-
await deleteFile2(
|
|
13906
|
-
await deleteFile2(
|
|
14250
|
+
await deleteFile2(path28.join(memoryPath, "events.jsonl"), "cleanup:memory/events.jsonl");
|
|
14251
|
+
await deleteFile2(path28.join(memoryPath, "learnings.jsonl"), "cleanup:memory/learnings.jsonl");
|
|
13907
14252
|
}
|
|
13908
14253
|
async function readJsonSafe(filePath) {
|
|
13909
14254
|
try {
|
|
13910
|
-
const content = await
|
|
14255
|
+
const content = await fs29.readFile(filePath, "utf-8");
|
|
13911
14256
|
return JSON.parse(content);
|
|
13912
14257
|
} catch (err) {
|
|
13913
14258
|
if (isNotFoundError(err) || err instanceof SyntaxError) {
|
|
@@ -15469,9 +15814,9 @@ ${errors.join("\n")}`);
|
|
|
15469
15814
|
});
|
|
15470
15815
|
|
|
15471
15816
|
// core/storage/storage.ts
|
|
15472
|
-
import
|
|
15817
|
+
import fs30 from "node:fs/promises";
|
|
15473
15818
|
import os8 from "node:os";
|
|
15474
|
-
import
|
|
15819
|
+
import path29 from "node:path";
|
|
15475
15820
|
function getStorage(projectId) {
|
|
15476
15821
|
return new FileStorage(projectId);
|
|
15477
15822
|
}
|
|
@@ -15489,7 +15834,7 @@ var init_storage = __esm({
|
|
|
15489
15834
|
basePath;
|
|
15490
15835
|
constructor(projectId) {
|
|
15491
15836
|
this.projectId = projectId;
|
|
15492
|
-
this.basePath =
|
|
15837
|
+
this.basePath = path29.join(os8.homedir(), ".prjct-cli/projects", projectId, "data");
|
|
15493
15838
|
}
|
|
15494
15839
|
/**
|
|
15495
15840
|
* Convert path array to file path
|
|
@@ -15498,17 +15843,17 @@ var init_storage = __esm({
|
|
|
15498
15843
|
*/
|
|
15499
15844
|
pathToFile(pathArray) {
|
|
15500
15845
|
if (pathArray.length === 1) {
|
|
15501
|
-
return
|
|
15846
|
+
return path29.join(this.basePath, `${pathArray[0]}.json`);
|
|
15502
15847
|
}
|
|
15503
15848
|
const dir = `${pathArray[0]}s`;
|
|
15504
15849
|
const rest = pathArray.slice(1);
|
|
15505
15850
|
const filename = `${rest.join("/")}.json`;
|
|
15506
|
-
return
|
|
15851
|
+
return path29.join(this.basePath, dir, filename);
|
|
15507
15852
|
}
|
|
15508
15853
|
async write(pathArray, data) {
|
|
15509
15854
|
const filePath = this.pathToFile(pathArray);
|
|
15510
|
-
await
|
|
15511
|
-
await
|
|
15855
|
+
await fs30.mkdir(path29.dirname(filePath), { recursive: true });
|
|
15856
|
+
await fs30.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
15512
15857
|
eventBus.publish({
|
|
15513
15858
|
type: inferEventType(pathArray, "write"),
|
|
15514
15859
|
path: pathArray,
|
|
@@ -15523,7 +15868,7 @@ var init_storage = __esm({
|
|
|
15523
15868
|
async read(pathArray) {
|
|
15524
15869
|
const filePath = this.pathToFile(pathArray);
|
|
15525
15870
|
try {
|
|
15526
|
-
const content = await
|
|
15871
|
+
const content = await fs30.readFile(filePath, "utf-8");
|
|
15527
15872
|
return JSON.parse(content);
|
|
15528
15873
|
} catch (error) {
|
|
15529
15874
|
if (isNotFoundError(error) || error instanceof SyntaxError) {
|
|
@@ -15533,9 +15878,9 @@ var init_storage = __esm({
|
|
|
15533
15878
|
}
|
|
15534
15879
|
}
|
|
15535
15880
|
async list(prefix) {
|
|
15536
|
-
const dir =
|
|
15881
|
+
const dir = path29.join(this.basePath, `${prefix[0]}s`);
|
|
15537
15882
|
try {
|
|
15538
|
-
const files = await
|
|
15883
|
+
const files = await fs30.readdir(dir);
|
|
15539
15884
|
return files.filter((f) => f.endsWith(".json") && f !== "index.json").map((f) => [...prefix, f.replace(".json", "")]);
|
|
15540
15885
|
} catch (error) {
|
|
15541
15886
|
if (isNotFoundError(error)) {
|
|
@@ -15547,7 +15892,7 @@ var init_storage = __esm({
|
|
|
15547
15892
|
async delete(pathArray) {
|
|
15548
15893
|
const filePath = this.pathToFile(pathArray);
|
|
15549
15894
|
try {
|
|
15550
|
-
await
|
|
15895
|
+
await fs30.unlink(filePath);
|
|
15551
15896
|
eventBus.publish({
|
|
15552
15897
|
type: inferEventType(pathArray, "delete"),
|
|
15553
15898
|
path: pathArray,
|
|
@@ -15567,7 +15912,7 @@ var init_storage = __esm({
|
|
|
15567
15912
|
async exists(pathArray) {
|
|
15568
15913
|
const filePath = this.pathToFile(pathArray);
|
|
15569
15914
|
try {
|
|
15570
|
-
await
|
|
15915
|
+
await fs30.access(filePath);
|
|
15571
15916
|
return true;
|
|
15572
15917
|
} catch (error) {
|
|
15573
15918
|
if (isNotFoundError(error)) {
|
|
@@ -15580,10 +15925,10 @@ var init_storage = __esm({
|
|
|
15580
15925
|
* Update collection index
|
|
15581
15926
|
*/
|
|
15582
15927
|
async updateIndex(collection, id, action) {
|
|
15583
|
-
const indexPath =
|
|
15928
|
+
const indexPath = path29.join(this.basePath, `${collection}s`, "index.json");
|
|
15584
15929
|
let index = { ids: [], updatedAt: "" };
|
|
15585
15930
|
try {
|
|
15586
|
-
const content = await
|
|
15931
|
+
const content = await fs30.readFile(indexPath, "utf-8");
|
|
15587
15932
|
index = JSON.parse(content);
|
|
15588
15933
|
} catch (error) {
|
|
15589
15934
|
if (!isNotFoundError(error) && !(error instanceof SyntaxError)) {
|
|
@@ -15596,8 +15941,8 @@ var init_storage = __esm({
|
|
|
15596
15941
|
index.ids = index.ids.filter((i) => i !== id);
|
|
15597
15942
|
}
|
|
15598
15943
|
index.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
15599
|
-
await
|
|
15600
|
-
await
|
|
15944
|
+
await fs30.mkdir(path29.dirname(indexPath), { recursive: true });
|
|
15945
|
+
await fs30.writeFile(indexPath, JSON.stringify(index, null, 2), "utf-8");
|
|
15601
15946
|
}
|
|
15602
15947
|
};
|
|
15603
15948
|
__name(getStorage, "getStorage");
|
|
@@ -15735,15 +16080,15 @@ var init_storage2 = __esm({
|
|
|
15735
16080
|
|
|
15736
16081
|
// core/agentic/domain-classifier.ts
|
|
15737
16082
|
import { createHash as createHash2 } from "node:crypto";
|
|
15738
|
-
import
|
|
15739
|
-
import
|
|
16083
|
+
import fs31 from "node:fs/promises";
|
|
16084
|
+
import path30 from "node:path";
|
|
15740
16085
|
function hashDescription(description) {
|
|
15741
16086
|
return createHash2("sha256").update(description.toLowerCase().trim()).digest("hex").slice(0, 16);
|
|
15742
16087
|
}
|
|
15743
16088
|
async function loadCache(globalPath) {
|
|
15744
16089
|
try {
|
|
15745
|
-
const cachePath =
|
|
15746
|
-
const content = await
|
|
16090
|
+
const cachePath = path30.join(globalPath, "storage", "classification-cache.json");
|
|
16091
|
+
const content = await fs31.readFile(cachePath, "utf-8");
|
|
15747
16092
|
return JSON.parse(content);
|
|
15748
16093
|
} catch (error) {
|
|
15749
16094
|
if (isNotFoundError(error)) return DEFAULT_CLASSIFICATION_CACHE;
|
|
@@ -15753,8 +16098,8 @@ async function loadCache(globalPath) {
|
|
|
15753
16098
|
}
|
|
15754
16099
|
async function saveCache(globalPath, cache2) {
|
|
15755
16100
|
try {
|
|
15756
|
-
const cachePath =
|
|
15757
|
-
await
|
|
16101
|
+
const cachePath = path30.join(globalPath, "storage", "classification-cache.json");
|
|
16102
|
+
await fs31.writeFile(cachePath, JSON.stringify(cache2, null, 2));
|
|
15758
16103
|
} catch (error) {
|
|
15759
16104
|
console.warn("[classifier] Failed to save cache:", getErrorMessage2(error));
|
|
15760
16105
|
}
|
|
@@ -16126,8 +16471,8 @@ var init_domain_classifier = __esm({
|
|
|
16126
16471
|
});
|
|
16127
16472
|
|
|
16128
16473
|
// core/agentic/template-loader.ts
|
|
16129
|
-
import
|
|
16130
|
-
import
|
|
16474
|
+
import fs32 from "node:fs/promises";
|
|
16475
|
+
import path31 from "node:path";
|
|
16131
16476
|
function updateLruOrder(key) {
|
|
16132
16477
|
const index = cacheOrder.indexOf(key);
|
|
16133
16478
|
if (index > -1) cacheOrder.splice(index, 1);
|
|
@@ -16165,9 +16510,9 @@ async function load(commandName) {
|
|
|
16165
16510
|
updateLruOrder(commandName);
|
|
16166
16511
|
return cache.get(commandName);
|
|
16167
16512
|
}
|
|
16168
|
-
const templatePath =
|
|
16513
|
+
const templatePath = path31.join(TEMPLATES_DIR, `${commandName}.md`);
|
|
16169
16514
|
try {
|
|
16170
|
-
const rawContent = await
|
|
16515
|
+
const rawContent = await fs32.readFile(templatePath, "utf-8");
|
|
16171
16516
|
const parsed = parseFrontmatter(rawContent);
|
|
16172
16517
|
evictLru();
|
|
16173
16518
|
cache.set(commandName, parsed);
|
|
@@ -16190,7 +16535,7 @@ var init_template_loader = __esm({
|
|
|
16190
16535
|
"core/agentic/template-loader.ts"() {
|
|
16191
16536
|
"use strict";
|
|
16192
16537
|
init_errors();
|
|
16193
|
-
TEMPLATES_DIR =
|
|
16538
|
+
TEMPLATES_DIR = path31.join(__dirname, "..", "..", "templates", "commands");
|
|
16194
16539
|
MAX_CACHE_SIZE = 50;
|
|
16195
16540
|
cache = /* @__PURE__ */ new Map();
|
|
16196
16541
|
cacheOrder = [];
|
|
@@ -16207,9 +16552,9 @@ var init_template_loader = __esm({
|
|
|
16207
16552
|
|
|
16208
16553
|
// core/agentic/orchestrator-executor.ts
|
|
16209
16554
|
import { exec as execCallback5 } from "node:child_process";
|
|
16210
|
-
import
|
|
16555
|
+
import fs33 from "node:fs/promises";
|
|
16211
16556
|
import os9 from "node:os";
|
|
16212
|
-
import
|
|
16557
|
+
import path32 from "node:path";
|
|
16213
16558
|
import { promisify as promisify7 } from "node:util";
|
|
16214
16559
|
var execAsync3, DOMAIN_DEPENDENCY_ORDER, OrchestratorExecutor, orchestratorExecutor, orchestrator_executor_default;
|
|
16215
16560
|
var init_orchestrator_executor = __esm({
|
|
@@ -16397,8 +16742,8 @@ var init_orchestrator_executor = __esm({
|
|
|
16397
16742
|
*/
|
|
16398
16743
|
async loadRepoAnalysis(globalPath) {
|
|
16399
16744
|
try {
|
|
16400
|
-
const analysisPath =
|
|
16401
|
-
const content = await
|
|
16745
|
+
const analysisPath = path32.join(globalPath, "analysis", "repo-analysis.json");
|
|
16746
|
+
const content = await fs33.readFile(analysisPath, "utf-8");
|
|
16402
16747
|
return JSON.parse(content);
|
|
16403
16748
|
} catch (error) {
|
|
16404
16749
|
if (isNotFoundError(error)) return null;
|
|
@@ -16423,8 +16768,8 @@ var init_orchestrator_executor = __esm({
|
|
|
16423
16768
|
hasDocker: false
|
|
16424
16769
|
};
|
|
16425
16770
|
try {
|
|
16426
|
-
const statePath =
|
|
16427
|
-
const stateContent = await
|
|
16771
|
+
const statePath = path32.join(globalPath, "storage", "state.json");
|
|
16772
|
+
const stateContent = await fs33.readFile(statePath, "utf-8");
|
|
16428
16773
|
const state = JSON.parse(stateContent);
|
|
16429
16774
|
if (state.domains) {
|
|
16430
16775
|
projectDomains = state.domains;
|
|
@@ -16458,8 +16803,8 @@ var init_orchestrator_executor = __esm({
|
|
|
16458
16803
|
*/
|
|
16459
16804
|
async getAvailableAgentNames(globalPath) {
|
|
16460
16805
|
try {
|
|
16461
|
-
const agentsDir =
|
|
16462
|
-
const files = await
|
|
16806
|
+
const agentsDir = path32.join(globalPath, "agents");
|
|
16807
|
+
const files = await fs33.readdir(agentsDir);
|
|
16463
16808
|
return files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
|
|
16464
16809
|
} catch {
|
|
16465
16810
|
return [];
|
|
@@ -16475,13 +16820,13 @@ var init_orchestrator_executor = __esm({
|
|
|
16475
16820
|
*/
|
|
16476
16821
|
async loadAgents(domains, projectId) {
|
|
16477
16822
|
const globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
16478
|
-
const agentsDir =
|
|
16823
|
+
const agentsDir = path32.join(globalPath, "agents");
|
|
16479
16824
|
const agentPromises = domains.map(async (domain) => {
|
|
16480
16825
|
const possibleNames = [`${domain}.md`, `${domain}-agent.md`, `prjct-${domain}.md`];
|
|
16481
16826
|
for (const fileName of possibleNames) {
|
|
16482
|
-
const filePath =
|
|
16827
|
+
const filePath = path32.join(agentsDir, fileName);
|
|
16483
16828
|
try {
|
|
16484
|
-
const content = await
|
|
16829
|
+
const content = await fs33.readFile(filePath, "utf-8");
|
|
16485
16830
|
const { frontmatter, body } = this.parseAgentFile(content);
|
|
16486
16831
|
return {
|
|
16487
16832
|
name: fileName.replace(".md", ""),
|
|
@@ -16522,7 +16867,7 @@ var init_orchestrator_executor = __esm({
|
|
|
16522
16867
|
* Uses parallel file reads for performance (PRJ-110).
|
|
16523
16868
|
*/
|
|
16524
16869
|
async loadSkills(agents) {
|
|
16525
|
-
const skillsDir =
|
|
16870
|
+
const skillsDir = path32.join(os9.homedir(), ".claude", "skills");
|
|
16526
16871
|
const skillToAgents = /* @__PURE__ */ new Map();
|
|
16527
16872
|
for (const agent of agents) {
|
|
16528
16873
|
for (const skillName of agent.skills) {
|
|
@@ -16533,14 +16878,14 @@ var init_orchestrator_executor = __esm({
|
|
|
16533
16878
|
}
|
|
16534
16879
|
const skillPromises = Array.from(skillToAgents.keys()).map(
|
|
16535
16880
|
async (skillName) => {
|
|
16536
|
-
const flatPath =
|
|
16537
|
-
const subdirPath =
|
|
16881
|
+
const flatPath = path32.join(skillsDir, `${skillName}.md`);
|
|
16882
|
+
const subdirPath = path32.join(skillsDir, skillName, "SKILL.md");
|
|
16538
16883
|
try {
|
|
16539
|
-
const content = await
|
|
16884
|
+
const content = await fs33.readFile(subdirPath, "utf-8");
|
|
16540
16885
|
return { name: skillName, content, filePath: subdirPath };
|
|
16541
16886
|
} catch {
|
|
16542
16887
|
try {
|
|
16543
|
-
const content = await
|
|
16888
|
+
const content = await fs33.readFile(flatPath, "utf-8");
|
|
16544
16889
|
return { name: skillName, content, filePath: flatPath };
|
|
16545
16890
|
} catch {
|
|
16546
16891
|
const agentNames = skillToAgents.get(skillName) || [];
|
|
@@ -17568,11 +17913,11 @@ var init_command_classifier = __esm({
|
|
|
17568
17913
|
});
|
|
17569
17914
|
|
|
17570
17915
|
// core/agentic/command-context.ts
|
|
17571
|
-
import
|
|
17572
|
-
import
|
|
17916
|
+
import fs34 from "node:fs/promises";
|
|
17917
|
+
import path33 from "node:path";
|
|
17573
17918
|
async function loadCommandContextConfig() {
|
|
17574
17919
|
if (cachedConfig) return cachedConfig;
|
|
17575
|
-
const raw = await
|
|
17920
|
+
const raw = await fs34.readFile(CONFIG_PATH, "utf-8");
|
|
17576
17921
|
const parsed = JSON.parse(raw);
|
|
17577
17922
|
cachedConfig = CommandContextConfigSchema.parse(parsed);
|
|
17578
17923
|
return cachedConfig;
|
|
@@ -17594,10 +17939,10 @@ function trackClassification(commandName, entry) {
|
|
|
17594
17939
|
return false;
|
|
17595
17940
|
}
|
|
17596
17941
|
async function persistClassification(commandName, entry) {
|
|
17597
|
-
const raw = await
|
|
17942
|
+
const raw = await fs34.readFile(CONFIG_PATH, "utf-8");
|
|
17598
17943
|
const config = JSON.parse(raw);
|
|
17599
17944
|
config.commands[commandName] = entry;
|
|
17600
|
-
await
|
|
17945
|
+
await fs34.writeFile(CONFIG_PATH, `${JSON.stringify(config, null, 2)}
|
|
17601
17946
|
`, "utf-8");
|
|
17602
17947
|
cachedConfig = null;
|
|
17603
17948
|
}
|
|
@@ -17631,7 +17976,7 @@ var init_command_context2 = __esm({
|
|
|
17631
17976
|
init_command_context();
|
|
17632
17977
|
init_version();
|
|
17633
17978
|
init_command_classifier();
|
|
17634
|
-
CONFIG_PATH =
|
|
17979
|
+
CONFIG_PATH = path33.join(PACKAGE_ROOT, "core/config/command-context.config.json");
|
|
17635
17980
|
cachedConfig = null;
|
|
17636
17981
|
__name(loadCommandContextConfig, "loadCommandContextConfig");
|
|
17637
17982
|
classificationCache = /* @__PURE__ */ new Map();
|
|
@@ -17814,8 +18159,8 @@ var init_injection_validator = __esm({
|
|
|
17814
18159
|
});
|
|
17815
18160
|
|
|
17816
18161
|
// core/agentic/prompt-builder.ts
|
|
17817
|
-
import
|
|
17818
|
-
import
|
|
18162
|
+
import fs35 from "node:fs/promises";
|
|
18163
|
+
import path34 from "node:path";
|
|
17819
18164
|
var PromptBuilder, promptBuilder, prompt_builder_default;
|
|
17820
18165
|
var init_prompt_builder = __esm({
|
|
17821
18166
|
"core/agentic/prompt-builder.ts"() {
|
|
@@ -17860,7 +18205,7 @@ var init_prompt_builder = __esm({
|
|
|
17860
18205
|
}
|
|
17861
18206
|
try {
|
|
17862
18207
|
if (await fileExists(templatePath)) {
|
|
17863
|
-
const content = await
|
|
18208
|
+
const content = await fs35.readFile(templatePath, "utf-8");
|
|
17864
18209
|
this._templateCache.set(templatePath, { content, loadedAt: now });
|
|
17865
18210
|
return content;
|
|
17866
18211
|
}
|
|
@@ -17924,7 +18269,7 @@ var init_prompt_builder = __esm({
|
|
|
17924
18269
|
* These modules extend the base global CLAUDE.md for complex operations
|
|
17925
18270
|
*/
|
|
17926
18271
|
async loadModule(moduleName) {
|
|
17927
|
-
const modulePath =
|
|
18272
|
+
const modulePath = path34.join(PACKAGE_ROOT, "templates/global/modules", moduleName);
|
|
17928
18273
|
return this.getTemplate(modulePath);
|
|
17929
18274
|
}
|
|
17930
18275
|
/**
|
|
@@ -17947,14 +18292,14 @@ var init_prompt_builder = __esm({
|
|
|
17947
18292
|
if (this._checklistsCache && now - this._checklistsCacheTime < this.TEMPLATE_CACHE_TTL_MS) {
|
|
17948
18293
|
return this._checklistsCache;
|
|
17949
18294
|
}
|
|
17950
|
-
const checklistsDir =
|
|
18295
|
+
const checklistsDir = path34.join(__dirname, "..", "..", "templates", "checklists");
|
|
17951
18296
|
const checklists = {};
|
|
17952
18297
|
try {
|
|
17953
18298
|
if (await fileExists(checklistsDir)) {
|
|
17954
|
-
const files = (await
|
|
18299
|
+
const files = (await fs35.readdir(checklistsDir)).filter((f) => f.endsWith(".md"));
|
|
17955
18300
|
for (const file of files) {
|
|
17956
18301
|
const name = file.replace(".md", "");
|
|
17957
|
-
const templatePath =
|
|
18302
|
+
const templatePath = path34.join(checklistsDir, file);
|
|
17958
18303
|
const content = await this.getTemplate(templatePath);
|
|
17959
18304
|
if (content) {
|
|
17960
18305
|
checklists[name] = content;
|
|
@@ -18074,7 +18419,7 @@ var init_prompt_builder = __esm({
|
|
|
18074
18419
|
if (this._checklistRoutingCache && now - this._checklistRoutingCacheTime < this.TEMPLATE_CACHE_TTL_MS) {
|
|
18075
18420
|
return this._checklistRoutingCache;
|
|
18076
18421
|
}
|
|
18077
|
-
const routingPath =
|
|
18422
|
+
const routingPath = path34.join(
|
|
18078
18423
|
__dirname,
|
|
18079
18424
|
"..",
|
|
18080
18425
|
"..",
|
|
@@ -18161,7 +18506,7 @@ Apply specialized expertise. Read agent file for details if needed.
|
|
|
18161
18506
|
}
|
|
18162
18507
|
const projectPath = context2.projectPath;
|
|
18163
18508
|
if (projectPath) {
|
|
18164
|
-
const projectName = orchestratorContext?.project?.id ?
|
|
18509
|
+
const projectName = orchestratorContext?.project?.id ? path34.basename(projectPath) : path34.basename(projectPath);
|
|
18165
18510
|
const envBlock = buildEnvironmentBlock({
|
|
18166
18511
|
projectName,
|
|
18167
18512
|
projectPath,
|
|
@@ -18657,8 +19002,8 @@ EXECUTE: Follow flow. Use tools. Decide.
|
|
|
18657
19002
|
});
|
|
18658
19003
|
|
|
18659
19004
|
// core/agentic/template-executor.ts
|
|
18660
|
-
import
|
|
18661
|
-
import
|
|
19005
|
+
import fs36 from "node:fs/promises";
|
|
19006
|
+
import path35 from "node:path";
|
|
18662
19007
|
var ORCHESTRATED_COMMANDS, SIMPLE_COMMANDS, TemplateExecutor, templateExecutor, template_executor_default;
|
|
18663
19008
|
var init_template_executor = __esm({
|
|
18664
19009
|
"core/agentic/template-executor.ts"() {
|
|
@@ -18676,7 +19021,7 @@ var init_template_executor = __esm({
|
|
|
18676
19021
|
* Get npm root for templates path
|
|
18677
19022
|
*/
|
|
18678
19023
|
async getNpmRoot() {
|
|
18679
|
-
const moduleDir =
|
|
19024
|
+
const moduleDir = path35.dirname(__require.resolve("prjct-cli/package.json"));
|
|
18680
19025
|
return moduleDir;
|
|
18681
19026
|
}
|
|
18682
19027
|
/**
|
|
@@ -18697,9 +19042,9 @@ var init_template_executor = __esm({
|
|
|
18697
19042
|
let templatesDir;
|
|
18698
19043
|
try {
|
|
18699
19044
|
const npmRoot = await this.getNpmRoot();
|
|
18700
|
-
templatesDir =
|
|
19045
|
+
templatesDir = path35.join(npmRoot, "templates");
|
|
18701
19046
|
} catch {
|
|
18702
|
-
templatesDir =
|
|
19047
|
+
templatesDir = path35.join(__dirname, "..", "..", "templates");
|
|
18703
19048
|
}
|
|
18704
19049
|
return {
|
|
18705
19050
|
projectPath,
|
|
@@ -18710,14 +19055,14 @@ var init_template_executor = __esm({
|
|
|
18710
19055
|
agentName: activeProvider.displayName,
|
|
18711
19056
|
agentSettingsPath: await path_manager_default.getAgentSettingsPath(),
|
|
18712
19057
|
paths: {
|
|
18713
|
-
orchestrator:
|
|
18714
|
-
agentRouting:
|
|
18715
|
-
taskFragmentation:
|
|
18716
|
-
commandTemplate:
|
|
18717
|
-
repoAnalysis:
|
|
18718
|
-
agentsDir:
|
|
19058
|
+
orchestrator: path35.join(templatesDir, "agentic", "orchestrator.md"),
|
|
19059
|
+
agentRouting: path35.join(templatesDir, "agentic", "agent-routing.md"),
|
|
19060
|
+
taskFragmentation: path35.join(templatesDir, "agentic", "task-fragmentation.md"),
|
|
19061
|
+
commandTemplate: path35.join(templatesDir, "commands", `${command}.md`),
|
|
19062
|
+
repoAnalysis: path35.join(globalPath, "analysis", "repo-analysis.json"),
|
|
19063
|
+
agentsDir: path35.join(globalPath, "agents"),
|
|
18719
19064
|
skillsDir: activeProvider.skillsDir,
|
|
18720
|
-
stateJson:
|
|
19065
|
+
stateJson: path35.join(globalPath, "storage", "state.json")
|
|
18721
19066
|
}
|
|
18722
19067
|
};
|
|
18723
19068
|
}
|
|
@@ -18735,8 +19080,8 @@ var init_template_executor = __esm({
|
|
|
18735
19080
|
async hasAgents(projectPath) {
|
|
18736
19081
|
try {
|
|
18737
19082
|
const projectId = await this.getProjectId(projectPath);
|
|
18738
|
-
const agentsDir =
|
|
18739
|
-
const files = await
|
|
19083
|
+
const agentsDir = path35.join(path_manager_default.getGlobalProjectPath(projectId), "agents");
|
|
19084
|
+
const files = await fs36.readdir(agentsDir);
|
|
18740
19085
|
return files.some((f) => f.endsWith(".md"));
|
|
18741
19086
|
} catch (error) {
|
|
18742
19087
|
if (isNotFoundError(error)) return false;
|
|
@@ -18749,8 +19094,8 @@ var init_template_executor = __esm({
|
|
|
18749
19094
|
async getAvailableAgents(projectPath) {
|
|
18750
19095
|
try {
|
|
18751
19096
|
const projectId = await this.getProjectId(projectPath);
|
|
18752
|
-
const agentsDir =
|
|
18753
|
-
const files = await
|
|
19097
|
+
const agentsDir = path35.join(path_manager_default.getGlobalProjectPath(projectId), "agents");
|
|
19098
|
+
const files = await fs36.readdir(agentsDir);
|
|
18754
19099
|
return files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
|
|
18755
19100
|
} catch {
|
|
18756
19101
|
return [];
|
|
@@ -18857,14 +19202,220 @@ When fragmenting tasks:
|
|
|
18857
19202
|
}
|
|
18858
19203
|
});
|
|
18859
19204
|
|
|
19205
|
+
// core/utils/retry.ts
|
|
19206
|
+
function isTransientError(error) {
|
|
19207
|
+
if (!error || typeof error !== "object") {
|
|
19208
|
+
return false;
|
|
19209
|
+
}
|
|
19210
|
+
const err = error;
|
|
19211
|
+
if (err.code && TRANSIENT_ERROR_CODES.has(err.code)) {
|
|
19212
|
+
return true;
|
|
19213
|
+
}
|
|
19214
|
+
if (err.code && PERMANENT_ERROR_CODES.has(err.code)) {
|
|
19215
|
+
return false;
|
|
19216
|
+
}
|
|
19217
|
+
if (err.message) {
|
|
19218
|
+
const msg = err.message.toLowerCase();
|
|
19219
|
+
if (msg.includes("timeout") || msg.includes("timed out")) {
|
|
19220
|
+
return true;
|
|
19221
|
+
}
|
|
19222
|
+
}
|
|
19223
|
+
return false;
|
|
19224
|
+
}
|
|
19225
|
+
function isPermanentError(error) {
|
|
19226
|
+
if (!error || typeof error !== "object") {
|
|
19227
|
+
return false;
|
|
19228
|
+
}
|
|
19229
|
+
const err = error;
|
|
19230
|
+
return !!(err.code && PERMANENT_ERROR_CODES.has(err.code));
|
|
19231
|
+
}
|
|
19232
|
+
function isCircuitOpen(operationId, threshold, timeoutMs) {
|
|
19233
|
+
const state = circuitStates.get(operationId);
|
|
19234
|
+
if (!state) {
|
|
19235
|
+
return false;
|
|
19236
|
+
}
|
|
19237
|
+
if (state.consecutiveFailures >= threshold && state.openedAt) {
|
|
19238
|
+
const elapsed = Date.now() - state.openedAt;
|
|
19239
|
+
if (elapsed >= timeoutMs) {
|
|
19240
|
+
circuitStates.delete(operationId);
|
|
19241
|
+
return false;
|
|
19242
|
+
}
|
|
19243
|
+
return true;
|
|
19244
|
+
}
|
|
19245
|
+
return false;
|
|
19246
|
+
}
|
|
19247
|
+
function recordFailure(operationId, threshold) {
|
|
19248
|
+
const state = circuitStates.get(operationId) || {
|
|
19249
|
+
consecutiveFailures: 0,
|
|
19250
|
+
openedAt: null
|
|
19251
|
+
};
|
|
19252
|
+
state.consecutiveFailures++;
|
|
19253
|
+
if (state.consecutiveFailures >= threshold && !state.openedAt) {
|
|
19254
|
+
state.openedAt = Date.now();
|
|
19255
|
+
}
|
|
19256
|
+
circuitStates.set(operationId, state);
|
|
19257
|
+
}
|
|
19258
|
+
function recordSuccess(operationId) {
|
|
19259
|
+
circuitStates.delete(operationId);
|
|
19260
|
+
}
|
|
19261
|
+
var TRANSIENT_ERROR_CODES, PERMANENT_ERROR_CODES, circuitStates, RetryPolicy, defaultAgentRetryPolicy, defaultToolRetryPolicy;
|
|
19262
|
+
var init_retry = __esm({
|
|
19263
|
+
"core/utils/retry.ts"() {
|
|
19264
|
+
"use strict";
|
|
19265
|
+
TRANSIENT_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
19266
|
+
"EBUSY",
|
|
19267
|
+
// Resource busy
|
|
19268
|
+
"EAGAIN",
|
|
19269
|
+
// Resource temporarily unavailable
|
|
19270
|
+
"ETIMEDOUT",
|
|
19271
|
+
// Operation timed out
|
|
19272
|
+
"ECONNRESET",
|
|
19273
|
+
// Connection reset by peer
|
|
19274
|
+
"ECONNREFUSED",
|
|
19275
|
+
// Connection refused (may be temporary)
|
|
19276
|
+
"ENOTFOUND",
|
|
19277
|
+
// DNS lookup failed (may be temporary)
|
|
19278
|
+
"EAI_AGAIN"
|
|
19279
|
+
// DNS temporary failure
|
|
19280
|
+
]);
|
|
19281
|
+
PERMANENT_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
19282
|
+
"ENOENT",
|
|
19283
|
+
// No such file or directory
|
|
19284
|
+
"EACCES",
|
|
19285
|
+
// Permission denied
|
|
19286
|
+
"EPERM",
|
|
19287
|
+
// Operation not permitted
|
|
19288
|
+
"EISDIR",
|
|
19289
|
+
// Is a directory
|
|
19290
|
+
"ENOTDIR",
|
|
19291
|
+
// Not a directory
|
|
19292
|
+
"EINVAL"
|
|
19293
|
+
// Invalid argument
|
|
19294
|
+
]);
|
|
19295
|
+
__name(isTransientError, "isTransientError");
|
|
19296
|
+
__name(isPermanentError, "isPermanentError");
|
|
19297
|
+
circuitStates = /* @__PURE__ */ new Map();
|
|
19298
|
+
__name(isCircuitOpen, "isCircuitOpen");
|
|
19299
|
+
__name(recordFailure, "recordFailure");
|
|
19300
|
+
__name(recordSuccess, "recordSuccess");
|
|
19301
|
+
RetryPolicy = class {
|
|
19302
|
+
static {
|
|
19303
|
+
__name(this, "RetryPolicy");
|
|
19304
|
+
}
|
|
19305
|
+
options;
|
|
19306
|
+
constructor(options = {}) {
|
|
19307
|
+
this.options = {
|
|
19308
|
+
maxAttempts: options.maxAttempts ?? 3,
|
|
19309
|
+
baseDelayMs: options.baseDelayMs ?? 1e3,
|
|
19310
|
+
maxDelayMs: options.maxDelayMs ?? 8e3,
|
|
19311
|
+
circuitBreakerThreshold: options.circuitBreakerThreshold ?? 5,
|
|
19312
|
+
circuitBreakerTimeoutMs: options.circuitBreakerTimeoutMs ?? 6e4
|
|
19313
|
+
};
|
|
19314
|
+
}
|
|
19315
|
+
/**
|
|
19316
|
+
* Execute an operation with retry logic
|
|
19317
|
+
*
|
|
19318
|
+
* @param operation - Async function to execute
|
|
19319
|
+
* @param operationId - Optional ID for circuit breaker tracking
|
|
19320
|
+
* @returns Result of the operation
|
|
19321
|
+
* @throws Error if all attempts fail or circuit is open
|
|
19322
|
+
*/
|
|
19323
|
+
async execute(operation, operationId = "default") {
|
|
19324
|
+
if (isCircuitOpen(
|
|
19325
|
+
operationId,
|
|
19326
|
+
this.options.circuitBreakerThreshold,
|
|
19327
|
+
this.options.circuitBreakerTimeoutMs
|
|
19328
|
+
)) {
|
|
19329
|
+
throw new Error(
|
|
19330
|
+
`Circuit breaker is open for operation: ${operationId}. Too many consecutive failures.`
|
|
19331
|
+
);
|
|
19332
|
+
}
|
|
19333
|
+
let lastError;
|
|
19334
|
+
let attempt = 0;
|
|
19335
|
+
while (attempt < this.options.maxAttempts) {
|
|
19336
|
+
try {
|
|
19337
|
+
const result = await operation();
|
|
19338
|
+
recordSuccess(operationId);
|
|
19339
|
+
return result;
|
|
19340
|
+
} catch (error) {
|
|
19341
|
+
lastError = error;
|
|
19342
|
+
attempt++;
|
|
19343
|
+
if (isPermanentError(error)) {
|
|
19344
|
+
recordFailure(operationId, this.options.circuitBreakerThreshold);
|
|
19345
|
+
throw error;
|
|
19346
|
+
}
|
|
19347
|
+
const shouldRetry = isTransientError(error) && attempt < this.options.maxAttempts;
|
|
19348
|
+
if (!shouldRetry) {
|
|
19349
|
+
recordFailure(operationId, this.options.circuitBreakerThreshold);
|
|
19350
|
+
throw error;
|
|
19351
|
+
}
|
|
19352
|
+
const delay = Math.min(
|
|
19353
|
+
this.options.baseDelayMs * 2 ** (attempt - 1),
|
|
19354
|
+
this.options.maxDelayMs
|
|
19355
|
+
);
|
|
19356
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
19357
|
+
}
|
|
19358
|
+
}
|
|
19359
|
+
recordFailure(operationId, this.options.circuitBreakerThreshold);
|
|
19360
|
+
throw lastError;
|
|
19361
|
+
}
|
|
19362
|
+
/**
|
|
19363
|
+
* Check if an error is transient (exposed for testing)
|
|
19364
|
+
*/
|
|
19365
|
+
isTransientError(error) {
|
|
19366
|
+
return isTransientError(error);
|
|
19367
|
+
}
|
|
19368
|
+
/**
|
|
19369
|
+
* Check if circuit is open for an operation (exposed for testing)
|
|
19370
|
+
*/
|
|
19371
|
+
isCircuitOpen(operationId) {
|
|
19372
|
+
return isCircuitOpen(
|
|
19373
|
+
operationId,
|
|
19374
|
+
this.options.circuitBreakerThreshold,
|
|
19375
|
+
this.options.circuitBreakerTimeoutMs
|
|
19376
|
+
);
|
|
19377
|
+
}
|
|
19378
|
+
/**
|
|
19379
|
+
* Get current circuit state for an operation (exposed for testing)
|
|
19380
|
+
*/
|
|
19381
|
+
getCircuitState(operationId) {
|
|
19382
|
+
return circuitStates.get(operationId);
|
|
19383
|
+
}
|
|
19384
|
+
/**
|
|
19385
|
+
* Reset circuit breaker for an operation (exposed for testing)
|
|
19386
|
+
*/
|
|
19387
|
+
resetCircuit(operationId) {
|
|
19388
|
+
circuitStates.delete(operationId);
|
|
19389
|
+
}
|
|
19390
|
+
/**
|
|
19391
|
+
* Reset all circuit breakers (exposed for testing)
|
|
19392
|
+
*/
|
|
19393
|
+
resetAllCircuits() {
|
|
19394
|
+
circuitStates.clear();
|
|
19395
|
+
}
|
|
19396
|
+
};
|
|
19397
|
+
defaultAgentRetryPolicy = new RetryPolicy({
|
|
19398
|
+
maxAttempts: 3,
|
|
19399
|
+
baseDelayMs: 1e3,
|
|
19400
|
+
maxDelayMs: 8e3
|
|
19401
|
+
});
|
|
19402
|
+
defaultToolRetryPolicy = new RetryPolicy({
|
|
19403
|
+
maxAttempts: 2,
|
|
19404
|
+
baseDelayMs: 500,
|
|
19405
|
+
maxDelayMs: 2e3
|
|
19406
|
+
});
|
|
19407
|
+
}
|
|
19408
|
+
});
|
|
19409
|
+
|
|
18860
19410
|
// core/agentic/tool-registry.ts
|
|
18861
19411
|
import { exec as exec7 } from "node:child_process";
|
|
18862
|
-
import
|
|
19412
|
+
import fs37 from "node:fs/promises";
|
|
18863
19413
|
import { promisify as promisify8 } from "node:util";
|
|
18864
19414
|
var execAsync4, toolRegistry, tool_registry_default;
|
|
18865
19415
|
var init_tool_registry = __esm({
|
|
18866
19416
|
"core/agentic/tool-registry.ts"() {
|
|
18867
19417
|
"use strict";
|
|
19418
|
+
init_retry();
|
|
18868
19419
|
execAsync4 = promisify8(exec7);
|
|
18869
19420
|
toolRegistry = {
|
|
18870
19421
|
tools: /* @__PURE__ */ new Map(),
|
|
@@ -18903,16 +19454,34 @@ var init_tool_registry = __esm({
|
|
|
18903
19454
|
};
|
|
18904
19455
|
toolRegistry.register("Read", async (filePath) => {
|
|
18905
19456
|
try {
|
|
18906
|
-
return await
|
|
18907
|
-
|
|
19457
|
+
return await defaultToolRetryPolicy.execute(
|
|
19458
|
+
async () => await fs37.readFile(filePath, "utf-8"),
|
|
19459
|
+
`read-${filePath}`
|
|
19460
|
+
);
|
|
19461
|
+
} catch (error) {
|
|
19462
|
+
if (isPermanentError(error)) {
|
|
19463
|
+
return null;
|
|
19464
|
+
}
|
|
19465
|
+
if (isTransientError(error)) {
|
|
19466
|
+
return null;
|
|
19467
|
+
}
|
|
18908
19468
|
return null;
|
|
18909
19469
|
}
|
|
18910
19470
|
});
|
|
18911
19471
|
toolRegistry.register("Write", async (filePath, content) => {
|
|
18912
19472
|
try {
|
|
18913
|
-
await
|
|
19473
|
+
await defaultToolRetryPolicy.execute(
|
|
19474
|
+
async () => await fs37.writeFile(filePath, content, "utf-8"),
|
|
19475
|
+
`write-${filePath}`
|
|
19476
|
+
);
|
|
18914
19477
|
return true;
|
|
18915
|
-
} catch (
|
|
19478
|
+
} catch (error) {
|
|
19479
|
+
if (isPermanentError(error)) {
|
|
19480
|
+
return false;
|
|
19481
|
+
}
|
|
19482
|
+
if (isTransientError(error)) {
|
|
19483
|
+
return false;
|
|
19484
|
+
}
|
|
18916
19485
|
return false;
|
|
18917
19486
|
}
|
|
18918
19487
|
});
|
|
@@ -18920,8 +19489,10 @@ var init_tool_registry = __esm({
|
|
|
18920
19489
|
"Bash",
|
|
18921
19490
|
async (command) => {
|
|
18922
19491
|
try {
|
|
18923
|
-
|
|
18924
|
-
|
|
19492
|
+
return await defaultToolRetryPolicy.execute(
|
|
19493
|
+
async () => await execAsync4(command),
|
|
19494
|
+
`bash-${command}`
|
|
19495
|
+
);
|
|
18925
19496
|
} catch (error) {
|
|
18926
19497
|
const err = error;
|
|
18927
19498
|
return {
|
|
@@ -18945,23 +19516,23 @@ var init_tool_registry = __esm({
|
|
|
18945
19516
|
});
|
|
18946
19517
|
|
|
18947
19518
|
// core/agentic/command-executor.ts
|
|
18948
|
-
import
|
|
19519
|
+
import fs38 from "node:fs/promises";
|
|
18949
19520
|
import os11 from "node:os";
|
|
18950
|
-
import
|
|
19521
|
+
import path36 from "node:path";
|
|
18951
19522
|
async function signalStart(commandName) {
|
|
18952
19523
|
try {
|
|
18953
|
-
const dir =
|
|
19524
|
+
const dir = path36.dirname(RUNNING_FILE);
|
|
18954
19525
|
if (!await fileExists(dir)) {
|
|
18955
|
-
await
|
|
19526
|
+
await fs38.mkdir(dir, { recursive: true });
|
|
18956
19527
|
}
|
|
18957
|
-
await
|
|
19528
|
+
await fs38.writeFile(RUNNING_FILE, `/p:${commandName}`);
|
|
18958
19529
|
} catch (_error) {
|
|
18959
19530
|
}
|
|
18960
19531
|
}
|
|
18961
19532
|
async function signalEnd() {
|
|
18962
19533
|
try {
|
|
18963
19534
|
if (await fileExists(RUNNING_FILE)) {
|
|
18964
|
-
await
|
|
19535
|
+
await fs38.unlink(RUNNING_FILE);
|
|
18965
19536
|
}
|
|
18966
19537
|
} catch (_error) {
|
|
18967
19538
|
}
|
|
@@ -18985,7 +19556,7 @@ var init_command_executor = __esm({
|
|
|
18985
19556
|
init_template_executor();
|
|
18986
19557
|
init_template_loader();
|
|
18987
19558
|
init_tool_registry();
|
|
18988
|
-
RUNNING_FILE =
|
|
19559
|
+
RUNNING_FILE = path36.join(os11.homedir(), ".prjct-cli", ".running");
|
|
18989
19560
|
__name(signalStart, "signalStart");
|
|
18990
19561
|
__name(signalEnd, "signalEnd");
|
|
18991
19562
|
CommandExecutor = class {
|
|
@@ -19294,10 +19865,10 @@ var init_command_executor = __esm({
|
|
|
19294
19865
|
});
|
|
19295
19866
|
|
|
19296
19867
|
// core/infrastructure/update-checker.ts
|
|
19297
|
-
import
|
|
19868
|
+
import fs39 from "node:fs/promises";
|
|
19298
19869
|
import https from "node:https";
|
|
19299
19870
|
import os12 from "node:os";
|
|
19300
|
-
import
|
|
19871
|
+
import path37 from "node:path";
|
|
19301
19872
|
import chalk8 from "chalk";
|
|
19302
19873
|
var UpdateChecker, update_checker_default;
|
|
19303
19874
|
var init_update_checker = __esm({
|
|
@@ -19315,8 +19886,8 @@ var init_update_checker = __esm({
|
|
|
19315
19886
|
checkInterval;
|
|
19316
19887
|
constructor() {
|
|
19317
19888
|
this.packageName = "prjct-cli";
|
|
19318
|
-
this.cacheDir =
|
|
19319
|
-
this.cacheFile =
|
|
19889
|
+
this.cacheDir = path37.join(os12.homedir(), ".prjct-cli", "config");
|
|
19890
|
+
this.cacheFile = path37.join(this.cacheDir, "update-cache.json");
|
|
19320
19891
|
this.checkInterval = 24 * 60 * 60 * 1e3;
|
|
19321
19892
|
}
|
|
19322
19893
|
/**
|
|
@@ -19324,8 +19895,8 @@ var init_update_checker = __esm({
|
|
|
19324
19895
|
*/
|
|
19325
19896
|
async getCurrentVersion() {
|
|
19326
19897
|
try {
|
|
19327
|
-
const packageJsonPath =
|
|
19328
|
-
const packageJson = JSON.parse(await
|
|
19898
|
+
const packageJsonPath = path37.join(__dirname, "..", "..", "package.json");
|
|
19899
|
+
const packageJson = JSON.parse(await fs39.readFile(packageJsonPath, "utf8"));
|
|
19329
19900
|
return packageJson.version;
|
|
19330
19901
|
} catch (error) {
|
|
19331
19902
|
console.error("Error reading package version:", getErrorMessage2(error));
|
|
@@ -19395,7 +19966,7 @@ var init_update_checker = __esm({
|
|
|
19395
19966
|
async readCache() {
|
|
19396
19967
|
try {
|
|
19397
19968
|
if (await fileExists(this.cacheFile)) {
|
|
19398
|
-
const cache2 = JSON.parse(await
|
|
19969
|
+
const cache2 = JSON.parse(await fs39.readFile(this.cacheFile, "utf8"));
|
|
19399
19970
|
return cache2;
|
|
19400
19971
|
}
|
|
19401
19972
|
} catch (_error) {
|
|
@@ -19408,9 +19979,9 @@ var init_update_checker = __esm({
|
|
|
19408
19979
|
async writeCache(data) {
|
|
19409
19980
|
try {
|
|
19410
19981
|
if (!await fileExists(this.cacheDir)) {
|
|
19411
|
-
await
|
|
19982
|
+
await fs39.mkdir(this.cacheDir, { recursive: true });
|
|
19412
19983
|
}
|
|
19413
|
-
await
|
|
19984
|
+
await fs39.writeFile(this.cacheFile, JSON.stringify(data, null, 2), "utf8");
|
|
19414
19985
|
} catch (_error) {
|
|
19415
19986
|
}
|
|
19416
19987
|
}
|
|
@@ -19564,12 +20135,13 @@ var init_agent_generator = __esm({
|
|
|
19564
20135
|
"core/services/agent-generator.ts"() {
|
|
19565
20136
|
"use strict";
|
|
19566
20137
|
init_preserve_sections();
|
|
20138
|
+
init_retry();
|
|
19567
20139
|
}
|
|
19568
20140
|
});
|
|
19569
20141
|
|
|
19570
20142
|
// core/agentic/agent-router.ts
|
|
19571
|
-
import
|
|
19572
|
-
import
|
|
20143
|
+
import fs40 from "node:fs/promises";
|
|
20144
|
+
import path38 from "node:path";
|
|
19573
20145
|
var AgentRouter, agent_router_default;
|
|
19574
20146
|
var init_agent_router = __esm({
|
|
19575
20147
|
"core/agentic/agent-router.ts"() {
|
|
@@ -19598,12 +20170,12 @@ var init_agent_router = __esm({
|
|
|
19598
20170
|
async loadAvailableAgents() {
|
|
19599
20171
|
if (!this.agentsPath) return [];
|
|
19600
20172
|
try {
|
|
19601
|
-
const files = await
|
|
20173
|
+
const files = await fs40.readdir(this.agentsPath);
|
|
19602
20174
|
const agents = [];
|
|
19603
20175
|
for (const file of files) {
|
|
19604
20176
|
if (file.endsWith(".md")) {
|
|
19605
20177
|
const name = file.replace(".md", "");
|
|
19606
|
-
const content = await
|
|
20178
|
+
const content = await fs40.readFile(path38.join(this.agentsPath, file), "utf-8");
|
|
19607
20179
|
agents.push({ name, content });
|
|
19608
20180
|
}
|
|
19609
20181
|
}
|
|
@@ -19628,8 +20200,8 @@ var init_agent_router = __esm({
|
|
|
19628
20200
|
async loadAgent(name) {
|
|
19629
20201
|
if (!this.agentsPath) return null;
|
|
19630
20202
|
try {
|
|
19631
|
-
const filePath =
|
|
19632
|
-
const content = await
|
|
20203
|
+
const filePath = path38.join(this.agentsPath, `${name}.md`);
|
|
20204
|
+
const content = await fs40.readFile(filePath, "utf-8");
|
|
19633
20205
|
return { name, content };
|
|
19634
20206
|
} catch (error) {
|
|
19635
20207
|
if (!isNotFoundError(error)) {
|
|
@@ -19657,7 +20229,7 @@ var init_agent_router = __esm({
|
|
|
19657
20229
|
*/
|
|
19658
20230
|
async logUsage(task, agent, _projectPath) {
|
|
19659
20231
|
try {
|
|
19660
|
-
const logPath =
|
|
20232
|
+
const logPath = path38.join(
|
|
19661
20233
|
process.env.HOME || "",
|
|
19662
20234
|
".prjct-cli",
|
|
19663
20235
|
"projects",
|
|
@@ -19671,7 +20243,7 @@ var init_agent_router = __esm({
|
|
|
19671
20243
|
projectId: this.projectId
|
|
19672
20244
|
})}
|
|
19673
20245
|
`;
|
|
19674
|
-
await
|
|
20246
|
+
await fs40.appendFile(logPath, entry);
|
|
19675
20247
|
} catch (error) {
|
|
19676
20248
|
if (!isNotFoundError(error)) {
|
|
19677
20249
|
console.error(`Agent usage log error: ${getErrorMessage2(error)}`);
|
|
@@ -19684,14 +20256,14 @@ var init_agent_router = __esm({
|
|
|
19684
20256
|
});
|
|
19685
20257
|
|
|
19686
20258
|
// core/infrastructure/agent-detector.ts
|
|
19687
|
-
import
|
|
20259
|
+
import path39 from "node:path";
|
|
19688
20260
|
async function isClaudeEnvironment() {
|
|
19689
20261
|
if (process.env.CLAUDE_AGENT || process.env.ANTHROPIC_CLAUDE) return true;
|
|
19690
20262
|
if (global.mcp || process.env.MCP_AVAILABLE) return true;
|
|
19691
20263
|
const projectRoot = process.cwd();
|
|
19692
|
-
if (await fileExists(
|
|
20264
|
+
if (await fileExists(path39.join(projectRoot, "CLAUDE.md"))) return true;
|
|
19693
20265
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
19694
|
-
if (await fileExists(
|
|
20266
|
+
if (await fileExists(path39.join(homeDir, ".claude"))) return true;
|
|
19695
20267
|
const cwd = process.cwd();
|
|
19696
20268
|
if (cwd.includes("/.claude/") || cwd.includes("/claude-workspace/")) return true;
|
|
19697
20269
|
return false;
|
|
@@ -19792,6 +20364,7 @@ var init_agent_service = __esm({
|
|
|
19792
20364
|
init_agent_router();
|
|
19793
20365
|
init_errors();
|
|
19794
20366
|
init_agent_detector();
|
|
20367
|
+
init_retry();
|
|
19795
20368
|
init_();
|
|
19796
20369
|
VALID_AGENT_TYPES = ["claude"];
|
|
19797
20370
|
AgentService = class {
|
|
@@ -19806,20 +20379,23 @@ var init_agent_service = __esm({
|
|
|
19806
20379
|
}
|
|
19807
20380
|
/**
|
|
19808
20381
|
* Initialize agent (Claude Code, Desktop, or Terminal)
|
|
20382
|
+
* Wrapped with retry policy to handle transient failures
|
|
19809
20383
|
*/
|
|
19810
20384
|
async initialize() {
|
|
19811
20385
|
if (this.agent) return this.agent;
|
|
19812
|
-
|
|
19813
|
-
|
|
19814
|
-
|
|
19815
|
-
|
|
19816
|
-
|
|
19817
|
-
|
|
19818
|
-
|
|
19819
|
-
|
|
19820
|
-
|
|
19821
|
-
|
|
19822
|
-
|
|
20386
|
+
return await defaultAgentRetryPolicy.execute(async () => {
|
|
20387
|
+
this.agentInfo = await detect2();
|
|
20388
|
+
if (!this.agentInfo?.isSupported) {
|
|
20389
|
+
throw AgentError.notSupported(this.agentInfo?.type ?? "unknown");
|
|
20390
|
+
}
|
|
20391
|
+
const agentType = this.agentInfo.type;
|
|
20392
|
+
if (!agentType || !VALID_AGENT_TYPES.includes(agentType)) {
|
|
20393
|
+
throw AgentError.notSupported(this.agentInfo?.type ?? "unknown");
|
|
20394
|
+
}
|
|
20395
|
+
const { default: Agent } = await globImport_infrastructure_agent(`../infrastructure/${agentType}-agent`);
|
|
20396
|
+
this.agent = new Agent();
|
|
20397
|
+
return this.agent;
|
|
20398
|
+
}, "agent-initialization");
|
|
19823
20399
|
}
|
|
19824
20400
|
/**
|
|
19825
20401
|
* Get current agent info
|
|
@@ -20313,7 +20889,7 @@ var init_context_selector = __esm({
|
|
|
20313
20889
|
});
|
|
20314
20890
|
|
|
20315
20891
|
// core/services/file-categorizer.ts
|
|
20316
|
-
import
|
|
20892
|
+
import path40 from "node:path";
|
|
20317
20893
|
var HEURISTIC_PATTERNS, FileCategorizer, fileCategorizer;
|
|
20318
20894
|
var init_file_categorizer = __esm({
|
|
20319
20895
|
"core/services/file-categorizer.ts"() {
|
|
@@ -20409,8 +20985,8 @@ var init_file_categorizer = __esm({
|
|
|
20409
20985
|
if (!domainPatterns.has(domain)) {
|
|
20410
20986
|
domainPatterns.set(domain, /* @__PURE__ */ new Set());
|
|
20411
20987
|
}
|
|
20412
|
-
const dir =
|
|
20413
|
-
domainPatterns.get(domain).add(`**/${
|
|
20988
|
+
const dir = path40.dirname(file.path);
|
|
20989
|
+
domainPatterns.get(domain).add(`**/${path40.basename(dir)}/**`);
|
|
20414
20990
|
}
|
|
20415
20991
|
}
|
|
20416
20992
|
}
|
|
@@ -20595,7 +21171,7 @@ var init_file_categorizer = __esm({
|
|
|
20595
21171
|
});
|
|
20596
21172
|
|
|
20597
21173
|
// core/services/file-scorer.ts
|
|
20598
|
-
import
|
|
21174
|
+
import path41 from "node:path";
|
|
20599
21175
|
var RELEVANCE_THRESHOLD, CONFIG_PATTERNS, IMPORTANT_NAME_PATTERNS, FileScorer, fileScorer;
|
|
20600
21176
|
var init_file_scorer = __esm({
|
|
20601
21177
|
"core/services/file-scorer.ts"() {
|
|
@@ -20730,7 +21306,7 @@ var init_file_scorer = __esm({
|
|
|
20730
21306
|
* Config files are always important
|
|
20731
21307
|
*/
|
|
20732
21308
|
calculateConfigRelevance(stats) {
|
|
20733
|
-
const filename =
|
|
21309
|
+
const filename = path41.basename(stats.path);
|
|
20734
21310
|
for (const pattern of CONFIG_PATTERNS) {
|
|
20735
21311
|
if (pattern.test(filename) || pattern.test(stats.path)) {
|
|
20736
21312
|
return 20;
|
|
@@ -20743,13 +21319,13 @@ var init_file_scorer = __esm({
|
|
|
20743
21319
|
* Certain filenames indicate importance
|
|
20744
21320
|
*/
|
|
20745
21321
|
calculateNameRelevance(stats) {
|
|
20746
|
-
const filename =
|
|
21322
|
+
const filename = path41.basename(stats.path);
|
|
20747
21323
|
for (const pattern of IMPORTANT_NAME_PATTERNS) {
|
|
20748
21324
|
if (pattern.test(filename)) {
|
|
20749
21325
|
return 15;
|
|
20750
21326
|
}
|
|
20751
21327
|
}
|
|
20752
|
-
const dir =
|
|
21328
|
+
const dir = path41.dirname(stats.path);
|
|
20753
21329
|
if (dir.includes("/api/") || dir.includes("/routes/")) return 10;
|
|
20754
21330
|
if (dir.includes("/components/") && filename.startsWith("index")) return 10;
|
|
20755
21331
|
if (dir.includes("/pages/") || dir.includes("/app/")) return 8;
|
|
@@ -21184,8 +21760,8 @@ var init_memory_service = __esm({
|
|
|
21184
21760
|
});
|
|
21185
21761
|
|
|
21186
21762
|
// core/services/nested-context-resolver.ts
|
|
21187
|
-
import
|
|
21188
|
-
import
|
|
21763
|
+
import fs41 from "node:fs/promises";
|
|
21764
|
+
import path42 from "node:path";
|
|
21189
21765
|
var NestedContextResolver;
|
|
21190
21766
|
var init_nested_context_resolver = __esm({
|
|
21191
21767
|
"core/services/nested-context-resolver.ts"() {
|
|
@@ -21199,7 +21775,7 @@ var init_nested_context_resolver = __esm({
|
|
|
21199
21775
|
rootPath;
|
|
21200
21776
|
monoInfo = null;
|
|
21201
21777
|
constructor(rootPath) {
|
|
21202
|
-
this.rootPath =
|
|
21778
|
+
this.rootPath = path42.resolve(rootPath);
|
|
21203
21779
|
}
|
|
21204
21780
|
/**
|
|
21205
21781
|
* Initialize the resolver with monorepo detection
|
|
@@ -21212,14 +21788,14 @@ var init_nested_context_resolver = __esm({
|
|
|
21212
21788
|
*/
|
|
21213
21789
|
async discoverContextFiles() {
|
|
21214
21790
|
const contexts = [];
|
|
21215
|
-
const rootPrjctPath =
|
|
21791
|
+
const rootPrjctPath = path42.join(this.rootPath, "PRJCT.md");
|
|
21216
21792
|
if (await fileExists2(rootPrjctPath)) {
|
|
21217
21793
|
const rootContext = await this.loadContext(rootPrjctPath, null);
|
|
21218
21794
|
contexts.push(rootContext);
|
|
21219
21795
|
}
|
|
21220
21796
|
if (this.monoInfo?.isMonorepo) {
|
|
21221
21797
|
for (const pkg of this.monoInfo.packages) {
|
|
21222
|
-
const pkgPrjctPath =
|
|
21798
|
+
const pkgPrjctPath = path42.join(pkg.path, "PRJCT.md");
|
|
21223
21799
|
if (await fileExists2(pkgPrjctPath)) {
|
|
21224
21800
|
const parentContext = contexts.find((c) => c.depth === 0) || null;
|
|
21225
21801
|
const pkgContext = await this.loadContext(pkgPrjctPath, parentContext, pkg);
|
|
@@ -21238,9 +21814,9 @@ var init_nested_context_resolver = __esm({
|
|
|
21238
21814
|
* Load a single PRJCT.md file into a NestedContext
|
|
21239
21815
|
*/
|
|
21240
21816
|
async loadContext(filePath, parent, pkg = null) {
|
|
21241
|
-
const content = await
|
|
21242
|
-
const relativePath =
|
|
21243
|
-
const depth = relativePath.split(
|
|
21817
|
+
const content = await fs41.readFile(filePath, "utf-8");
|
|
21818
|
+
const relativePath = path42.relative(this.rootPath, filePath);
|
|
21819
|
+
const depth = relativePath.split(path42.sep).length - 1;
|
|
21244
21820
|
return {
|
|
21245
21821
|
path: filePath,
|
|
21246
21822
|
relativePath,
|
|
@@ -21294,14 +21870,14 @@ var init_nested_context_resolver = __esm({
|
|
|
21294
21870
|
const scan = /* @__PURE__ */ __name(async (currentDir, depth) => {
|
|
21295
21871
|
if (depth > 5) return;
|
|
21296
21872
|
try {
|
|
21297
|
-
const entries = await
|
|
21873
|
+
const entries = await fs41.readdir(currentDir, { withFileTypes: true });
|
|
21298
21874
|
for (const entry of entries) {
|
|
21299
21875
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
|
|
21300
21876
|
continue;
|
|
21301
21877
|
}
|
|
21302
21878
|
if (entry.isDirectory()) {
|
|
21303
|
-
const subDir =
|
|
21304
|
-
const prjctPath =
|
|
21879
|
+
const subDir = path42.join(currentDir, entry.name);
|
|
21880
|
+
const prjctPath = path42.join(subDir, "PRJCT.md");
|
|
21305
21881
|
if (await fileExists2(prjctPath) && !existingPaths.has(prjctPath)) {
|
|
21306
21882
|
const parent = this.findParentContext(prjctPath, existing.concat(found));
|
|
21307
21883
|
const context2 = await this.loadContext(prjctPath, parent);
|
|
@@ -21324,10 +21900,10 @@ var init_nested_context_resolver = __esm({
|
|
|
21324
21900
|
* Find the parent context for a given path
|
|
21325
21901
|
*/
|
|
21326
21902
|
findParentContext(filePath, contexts) {
|
|
21327
|
-
const fileDir =
|
|
21903
|
+
const fileDir = path42.dirname(filePath);
|
|
21328
21904
|
const sorted = [...contexts].sort((a, b) => b.depth - a.depth);
|
|
21329
21905
|
for (const ctx of sorted) {
|
|
21330
|
-
const ctxDir =
|
|
21906
|
+
const ctxDir = path42.dirname(ctx.path);
|
|
21331
21907
|
if (fileDir.startsWith(ctxDir) && fileDir !== ctxDir) {
|
|
21332
21908
|
return ctx;
|
|
21333
21909
|
}
|
|
@@ -21340,10 +21916,10 @@ var init_nested_context_resolver = __esm({
|
|
|
21340
21916
|
*/
|
|
21341
21917
|
async resolveContextForPath(targetPath) {
|
|
21342
21918
|
const contexts = await this.discoverContextFiles();
|
|
21343
|
-
const targetDir =
|
|
21919
|
+
const targetDir = path42.resolve(targetPath);
|
|
21344
21920
|
let bestMatch = null;
|
|
21345
21921
|
for (const ctx of contexts) {
|
|
21346
|
-
const ctxDir =
|
|
21922
|
+
const ctxDir = path42.dirname(ctx.path);
|
|
21347
21923
|
if (targetDir.startsWith(ctxDir)) {
|
|
21348
21924
|
if (!bestMatch || ctx.depth > bestMatch.depth) {
|
|
21349
21925
|
bestMatch = ctx;
|
|
@@ -21435,14 +22011,14 @@ ${content}`);
|
|
|
21435
22011
|
*/
|
|
21436
22012
|
async discoverAgentFiles() {
|
|
21437
22013
|
const agentFiles = [];
|
|
21438
|
-
const rootAgentsPath =
|
|
22014
|
+
const rootAgentsPath = path42.join(this.rootPath, "AGENTS.md");
|
|
21439
22015
|
if (await fileExists2(rootAgentsPath)) {
|
|
21440
22016
|
const rootAgents = await this.loadAgents(rootAgentsPath, null);
|
|
21441
22017
|
agentFiles.push(rootAgents);
|
|
21442
22018
|
}
|
|
21443
22019
|
if (this.monoInfo?.isMonorepo) {
|
|
21444
22020
|
for (const pkg of this.monoInfo.packages) {
|
|
21445
|
-
const pkgAgentsPath =
|
|
22021
|
+
const pkgAgentsPath = path42.join(pkg.path, "AGENTS.md");
|
|
21446
22022
|
if (await fileExists2(pkgAgentsPath)) {
|
|
21447
22023
|
const parentAgents = agentFiles.find((a) => a.depth === 0) || null;
|
|
21448
22024
|
const pkgAgents = await this.loadAgents(pkgAgentsPath, parentAgents, pkg);
|
|
@@ -21461,9 +22037,9 @@ ${content}`);
|
|
|
21461
22037
|
* Load a single AGENTS.md file into a NestedAgents structure
|
|
21462
22038
|
*/
|
|
21463
22039
|
async loadAgents(filePath, parent, pkg = null) {
|
|
21464
|
-
const content = await
|
|
21465
|
-
const relativePath =
|
|
21466
|
-
const depth = relativePath.split(
|
|
22040
|
+
const content = await fs41.readFile(filePath, "utf-8");
|
|
22041
|
+
const relativePath = path42.relative(this.rootPath, filePath);
|
|
22042
|
+
const depth = relativePath.split(path42.sep).length - 1;
|
|
21467
22043
|
return {
|
|
21468
22044
|
path: filePath,
|
|
21469
22045
|
relativePath,
|
|
@@ -21596,14 +22172,14 @@ ${content}`);
|
|
|
21596
22172
|
const scan = /* @__PURE__ */ __name(async (currentDir, depth) => {
|
|
21597
22173
|
if (depth > 5) return;
|
|
21598
22174
|
try {
|
|
21599
|
-
const entries = await
|
|
22175
|
+
const entries = await fs41.readdir(currentDir, { withFileTypes: true });
|
|
21600
22176
|
for (const entry of entries) {
|
|
21601
22177
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
|
|
21602
22178
|
continue;
|
|
21603
22179
|
}
|
|
21604
22180
|
if (entry.isDirectory()) {
|
|
21605
|
-
const subDir =
|
|
21606
|
-
const agentsPath =
|
|
22181
|
+
const subDir = path42.join(currentDir, entry.name);
|
|
22182
|
+
const agentsPath = path42.join(subDir, "AGENTS.md");
|
|
21607
22183
|
if (await fileExists2(agentsPath) && !existingPaths.has(agentsPath)) {
|
|
21608
22184
|
const parent = this.findParentAgents(agentsPath, existing.concat(found));
|
|
21609
22185
|
const agents = await this.loadAgents(agentsPath, parent);
|
|
@@ -21626,10 +22202,10 @@ ${content}`);
|
|
|
21626
22202
|
* Find the parent agents file for a given path
|
|
21627
22203
|
*/
|
|
21628
22204
|
findParentAgents(filePath, agentFiles) {
|
|
21629
|
-
const fileDir =
|
|
22205
|
+
const fileDir = path42.dirname(filePath);
|
|
21630
22206
|
const sorted = [...agentFiles].sort((a, b) => b.depth - a.depth);
|
|
21631
22207
|
for (const agents of sorted) {
|
|
21632
|
-
const agentsDir =
|
|
22208
|
+
const agentsDir = path42.dirname(agents.path);
|
|
21633
22209
|
if (fileDir.startsWith(agentsDir) && fileDir !== agentsDir) {
|
|
21634
22210
|
return agents;
|
|
21635
22211
|
}
|
|
@@ -21642,10 +22218,10 @@ ${content}`);
|
|
|
21642
22218
|
*/
|
|
21643
22219
|
async resolveAgentsForPath(targetPath) {
|
|
21644
22220
|
const agentFiles = await this.discoverAgentFiles();
|
|
21645
|
-
const targetDir =
|
|
22221
|
+
const targetDir = path42.resolve(targetPath);
|
|
21646
22222
|
let bestMatch = null;
|
|
21647
22223
|
for (const agents of agentFiles) {
|
|
21648
|
-
const agentsDir =
|
|
22224
|
+
const agentsDir = path42.dirname(agents.path);
|
|
21649
22225
|
if (targetDir.startsWith(agentsDir)) {
|
|
21650
22226
|
if (!bestMatch || agents.depth > bestMatch.depth) {
|
|
21651
22227
|
bestMatch = agents;
|
|
@@ -22087,16 +22663,16 @@ var init_onboarding = __esm({
|
|
|
22087
22663
|
* Detect project type from file system
|
|
22088
22664
|
*/
|
|
22089
22665
|
async detectProjectType() {
|
|
22090
|
-
const
|
|
22091
|
-
const
|
|
22666
|
+
const fs62 = await import("node:fs/promises");
|
|
22667
|
+
const path74 = await import("node:path");
|
|
22092
22668
|
try {
|
|
22093
|
-
const files = await
|
|
22669
|
+
const files = await fs62.readdir(this.projectPath);
|
|
22094
22670
|
if (files.includes("turbo.json") || files.includes("lerna.json") || files.includes("nx.json")) {
|
|
22095
22671
|
return "monorepo";
|
|
22096
22672
|
}
|
|
22097
22673
|
if (files.includes("package.json")) {
|
|
22098
|
-
const pkgPath =
|
|
22099
|
-
const pkgContent = await
|
|
22674
|
+
const pkgPath = path74.join(this.projectPath, "package.json");
|
|
22675
|
+
const pkgContent = await fs62.readFile(pkgPath, "utf-8");
|
|
22100
22676
|
const pkg = JSON.parse(pkgContent);
|
|
22101
22677
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
22102
22678
|
if (pkg.bin) return "cli-tool";
|
|
@@ -22132,32 +22708,32 @@ var init_onboarding = __esm({
|
|
|
22132
22708
|
* Detect installed AI agents from config files
|
|
22133
22709
|
*/
|
|
22134
22710
|
async detectInstalledAgents() {
|
|
22135
|
-
const
|
|
22136
|
-
const
|
|
22711
|
+
const fs62 = await import("node:fs/promises");
|
|
22712
|
+
const path74 = await import("node:path");
|
|
22137
22713
|
const os22 = await import("node:os");
|
|
22138
22714
|
const agents = [];
|
|
22139
22715
|
try {
|
|
22140
|
-
await
|
|
22716
|
+
await fs62.access(path74.join(os22.homedir(), ".claude"));
|
|
22141
22717
|
agents.push("claude");
|
|
22142
22718
|
} catch {
|
|
22143
22719
|
}
|
|
22144
22720
|
try {
|
|
22145
|
-
await
|
|
22721
|
+
await fs62.access(path74.join(this.projectPath, ".cursorrules"));
|
|
22146
22722
|
agents.push("cursor");
|
|
22147
22723
|
} catch {
|
|
22148
22724
|
}
|
|
22149
22725
|
try {
|
|
22150
|
-
await
|
|
22726
|
+
await fs62.access(path74.join(this.projectPath, ".windsurfrules"));
|
|
22151
22727
|
agents.push("windsurf");
|
|
22152
22728
|
} catch {
|
|
22153
22729
|
}
|
|
22154
22730
|
try {
|
|
22155
|
-
await
|
|
22731
|
+
await fs62.access(path74.join(this.projectPath, ".github", "copilot-instructions.md"));
|
|
22156
22732
|
agents.push("copilot");
|
|
22157
22733
|
} catch {
|
|
22158
22734
|
}
|
|
22159
22735
|
try {
|
|
22160
|
-
await
|
|
22736
|
+
await fs62.access(path74.join(os22.homedir(), ".gemini"));
|
|
22161
22737
|
agents.push("gemini");
|
|
22162
22738
|
} catch {
|
|
22163
22739
|
}
|
|
@@ -22167,17 +22743,17 @@ var init_onboarding = __esm({
|
|
|
22167
22743
|
* Detect tech stack from project files
|
|
22168
22744
|
*/
|
|
22169
22745
|
async detectStack() {
|
|
22170
|
-
const
|
|
22171
|
-
const
|
|
22746
|
+
const fs62 = await import("node:fs/promises");
|
|
22747
|
+
const path74 = await import("node:path");
|
|
22172
22748
|
const stack = {
|
|
22173
22749
|
language: "Unknown",
|
|
22174
22750
|
technologies: []
|
|
22175
22751
|
};
|
|
22176
22752
|
try {
|
|
22177
|
-
const files = await
|
|
22753
|
+
const files = await fs62.readdir(this.projectPath);
|
|
22178
22754
|
if (files.includes("package.json")) {
|
|
22179
|
-
const pkgPath =
|
|
22180
|
-
const pkgContent = await
|
|
22755
|
+
const pkgPath = path74.join(this.projectPath, "package.json");
|
|
22756
|
+
const pkgContent = await fs62.readFile(pkgPath, "utf-8");
|
|
22181
22757
|
const pkg = JSON.parse(pkgContent);
|
|
22182
22758
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
22183
22759
|
stack.language = deps.typescript ? "TypeScript" : "JavaScript";
|
|
@@ -22284,14 +22860,14 @@ var init_wizard = __esm({
|
|
|
22284
22860
|
|
|
22285
22861
|
// core/context/generator.ts
|
|
22286
22862
|
import { exec as exec10 } from "node:child_process";
|
|
22287
|
-
import
|
|
22288
|
-
import
|
|
22863
|
+
import fs42 from "node:fs/promises";
|
|
22864
|
+
import path43 from "node:path";
|
|
22289
22865
|
import { promisify as promisify11 } from "node:util";
|
|
22290
22866
|
async function generateContext(projectId, repoPath) {
|
|
22291
22867
|
const _globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
22292
22868
|
const contextPath = path_manager_default.getContextPath(projectId);
|
|
22293
22869
|
const storage = getStorage(projectId);
|
|
22294
|
-
await
|
|
22870
|
+
await fs42.mkdir(contextPath, { recursive: true });
|
|
22295
22871
|
const project = await storage.read(["project"]) || {};
|
|
22296
22872
|
const taskPaths = await storage.list(["task"]);
|
|
22297
22873
|
const featurePaths = await storage.list(["feature"]);
|
|
@@ -22373,8 +22949,8 @@ async function getPackageData(repoPath) {
|
|
|
22373
22949
|
scripts: {}
|
|
22374
22950
|
};
|
|
22375
22951
|
try {
|
|
22376
|
-
const pkgPath =
|
|
22377
|
-
const pkg = JSON.parse(await
|
|
22952
|
+
const pkgPath = path43.join(repoPath, "package.json");
|
|
22953
|
+
const pkg = JSON.parse(await fs42.readFile(pkgPath, "utf-8"));
|
|
22378
22954
|
data.dependencies = pkg.dependencies || {};
|
|
22379
22955
|
data.devDependencies = pkg.devDependencies || {};
|
|
22380
22956
|
data.scripts = pkg.scripts || {};
|
|
@@ -22383,7 +22959,7 @@ async function getPackageData(repoPath) {
|
|
|
22383
22959
|
return data;
|
|
22384
22960
|
}
|
|
22385
22961
|
async function generateClaudeMd(contextPath, projectId, project, tasks, features, ideas, agents, gitData, pkgData, repoPath) {
|
|
22386
|
-
const projectName = project.name ||
|
|
22962
|
+
const projectName = project.name || path43.basename(repoPath);
|
|
22387
22963
|
const currentTask = tasks.find((t) => t.status === "in_progress");
|
|
22388
22964
|
const pendingTasks = tasks.filter((t) => t.status === "pending");
|
|
22389
22965
|
const activeFeatures = features.filter((f) => f.status === "in_progress" || f.status === "active");
|
|
@@ -22458,7 +23034,7 @@ ${agents.length > 0 ? agents.map((a) => `- **${a.name}**: ${a.role || "Specialis
|
|
|
22458
23034
|
\u2514\u2500\u2500 pending.json
|
|
22459
23035
|
\`\`\`
|
|
22460
23036
|
`;
|
|
22461
|
-
await
|
|
23037
|
+
await fs42.writeFile(path43.join(contextPath, "CLAUDE.md"), content, "utf-8");
|
|
22462
23038
|
}
|
|
22463
23039
|
async function generateNowMd(contextPath, tasks) {
|
|
22464
23040
|
const currentTask = tasks.find((t) => t.status === "in_progress");
|
|
@@ -22473,7 +23049,7 @@ async function generateNowMd(contextPath, tasks) {
|
|
|
22473
23049
|
|
|
22474
23050
|
_No active task. Use /p:now to start._
|
|
22475
23051
|
`;
|
|
22476
|
-
await
|
|
23052
|
+
await fs42.writeFile(path43.join(contextPath, "now.md"), content, "utf-8");
|
|
22477
23053
|
}
|
|
22478
23054
|
async function generateQueueMd(contextPath, tasks) {
|
|
22479
23055
|
const pendingTasks = tasks.filter((t) => t.status === "pending");
|
|
@@ -22481,7 +23057,7 @@ async function generateQueueMd(contextPath, tasks) {
|
|
|
22481
23057
|
|
|
22482
23058
|
${pendingTasks.length > 0 ? pendingTasks.map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ""}`).join("\n") : "_Empty queue. Use /p:next to add tasks._"}
|
|
22483
23059
|
`;
|
|
22484
|
-
await
|
|
23060
|
+
await fs42.writeFile(path43.join(contextPath, "queue.md"), content, "utf-8");
|
|
22485
23061
|
}
|
|
22486
23062
|
async function generateSummaryMd(contextPath, project, gitData, pkgData) {
|
|
22487
23063
|
const content = `# PROJECT SUMMARY
|
|
@@ -22501,7 +23077,7 @@ async function generateSummaryMd(contextPath, project, gitData, pkgData) {
|
|
|
22501
23077
|
- Production: ${Object.keys(pkgData.dependencies).length}
|
|
22502
23078
|
- Dev: ${Object.keys(pkgData.devDependencies).length}
|
|
22503
23079
|
`;
|
|
22504
|
-
await
|
|
23080
|
+
await fs42.writeFile(path43.join(contextPath, "summary.md"), content, "utf-8");
|
|
22505
23081
|
}
|
|
22506
23082
|
var execAsync7;
|
|
22507
23083
|
var init_generator = __esm({
|
|
@@ -22522,8 +23098,8 @@ var init_generator = __esm({
|
|
|
22522
23098
|
|
|
22523
23099
|
// core/domain/analyzer.ts
|
|
22524
23100
|
import { exec as execCallback6 } from "node:child_process";
|
|
22525
|
-
import
|
|
22526
|
-
import
|
|
23101
|
+
import fs43 from "node:fs/promises";
|
|
23102
|
+
import path44 from "node:path";
|
|
22527
23103
|
import { promisify as promisify12 } from "node:util";
|
|
22528
23104
|
var exec11, CodebaseAnalyzer, analyzer, analyzer_default2;
|
|
22529
23105
|
var init_analyzer2 = __esm({
|
|
@@ -22547,8 +23123,8 @@ var init_analyzer2 = __esm({
|
|
|
22547
23123
|
*/
|
|
22548
23124
|
async readPackageJson() {
|
|
22549
23125
|
try {
|
|
22550
|
-
const packagePath =
|
|
22551
|
-
const content = await
|
|
23126
|
+
const packagePath = path44.join(this.projectPath, "package.json");
|
|
23127
|
+
const content = await fs43.readFile(packagePath, "utf-8");
|
|
22552
23128
|
return JSON.parse(content);
|
|
22553
23129
|
} catch (error) {
|
|
22554
23130
|
if (isNotFoundError(error) || error instanceof SyntaxError) {
|
|
@@ -22562,8 +23138,8 @@ var init_analyzer2 = __esm({
|
|
|
22562
23138
|
*/
|
|
22563
23139
|
async readCargoToml() {
|
|
22564
23140
|
try {
|
|
22565
|
-
const cargoPath =
|
|
22566
|
-
return await
|
|
23141
|
+
const cargoPath = path44.join(this.projectPath, "Cargo.toml");
|
|
23142
|
+
return await fs43.readFile(cargoPath, "utf-8");
|
|
22567
23143
|
} catch (error) {
|
|
22568
23144
|
if (isNotFoundError(error)) {
|
|
22569
23145
|
return null;
|
|
@@ -22576,8 +23152,8 @@ var init_analyzer2 = __esm({
|
|
|
22576
23152
|
*/
|
|
22577
23153
|
async readRequirements() {
|
|
22578
23154
|
try {
|
|
22579
|
-
const reqPath =
|
|
22580
|
-
return await
|
|
23155
|
+
const reqPath = path44.join(this.projectPath, "requirements.txt");
|
|
23156
|
+
return await fs43.readFile(reqPath, "utf-8");
|
|
22581
23157
|
} catch (error) {
|
|
22582
23158
|
if (isNotFoundError(error)) {
|
|
22583
23159
|
return null;
|
|
@@ -22590,8 +23166,8 @@ var init_analyzer2 = __esm({
|
|
|
22590
23166
|
*/
|
|
22591
23167
|
async readGoMod() {
|
|
22592
23168
|
try {
|
|
22593
|
-
const goModPath =
|
|
22594
|
-
return await
|
|
23169
|
+
const goModPath = path44.join(this.projectPath, "go.mod");
|
|
23170
|
+
return await fs43.readFile(goModPath, "utf-8");
|
|
22595
23171
|
} catch (error) {
|
|
22596
23172
|
if (isNotFoundError(error)) {
|
|
22597
23173
|
return null;
|
|
@@ -22604,8 +23180,8 @@ var init_analyzer2 = __esm({
|
|
|
22604
23180
|
*/
|
|
22605
23181
|
async readGemfile() {
|
|
22606
23182
|
try {
|
|
22607
|
-
const gemfilePath =
|
|
22608
|
-
return await
|
|
23183
|
+
const gemfilePath = path44.join(this.projectPath, "Gemfile");
|
|
23184
|
+
return await fs43.readFile(gemfilePath, "utf-8");
|
|
22609
23185
|
} catch (error) {
|
|
22610
23186
|
if (isNotFoundError(error)) {
|
|
22611
23187
|
return null;
|
|
@@ -22618,8 +23194,8 @@ var init_analyzer2 = __esm({
|
|
|
22618
23194
|
*/
|
|
22619
23195
|
async readMixExs() {
|
|
22620
23196
|
try {
|
|
22621
|
-
const mixPath =
|
|
22622
|
-
return await
|
|
23197
|
+
const mixPath = path44.join(this.projectPath, "mix.exs");
|
|
23198
|
+
return await fs43.readFile(mixPath, "utf-8");
|
|
22623
23199
|
} catch (error) {
|
|
22624
23200
|
if (isNotFoundError(error)) {
|
|
22625
23201
|
return null;
|
|
@@ -22632,8 +23208,8 @@ var init_analyzer2 = __esm({
|
|
|
22632
23208
|
*/
|
|
22633
23209
|
async readPomXml() {
|
|
22634
23210
|
try {
|
|
22635
|
-
const pomPath =
|
|
22636
|
-
return await
|
|
23211
|
+
const pomPath = path44.join(this.projectPath, "pom.xml");
|
|
23212
|
+
return await fs43.readFile(pomPath, "utf-8");
|
|
22637
23213
|
} catch (error) {
|
|
22638
23214
|
if (isNotFoundError(error)) {
|
|
22639
23215
|
return null;
|
|
@@ -22646,8 +23222,8 @@ var init_analyzer2 = __esm({
|
|
|
22646
23222
|
*/
|
|
22647
23223
|
async readComposerJson() {
|
|
22648
23224
|
try {
|
|
22649
|
-
const composerPath =
|
|
22650
|
-
const content = await
|
|
23225
|
+
const composerPath = path44.join(this.projectPath, "composer.json");
|
|
23226
|
+
const content = await fs43.readFile(composerPath, "utf-8");
|
|
22651
23227
|
return JSON.parse(content);
|
|
22652
23228
|
} catch (error) {
|
|
22653
23229
|
if (isNotFoundError(error) || error instanceof SyntaxError) {
|
|
@@ -22661,8 +23237,8 @@ var init_analyzer2 = __esm({
|
|
|
22661
23237
|
*/
|
|
22662
23238
|
async readPyprojectToml() {
|
|
22663
23239
|
try {
|
|
22664
|
-
const pyprojectPath =
|
|
22665
|
-
return await
|
|
23240
|
+
const pyprojectPath = path44.join(this.projectPath, "pyproject.toml");
|
|
23241
|
+
return await fs43.readFile(pyprojectPath, "utf-8");
|
|
22666
23242
|
} catch (error) {
|
|
22667
23243
|
if (isNotFoundError(error)) {
|
|
22668
23244
|
return null;
|
|
@@ -22698,7 +23274,7 @@ var init_analyzer2 = __esm({
|
|
|
22698
23274
|
*/
|
|
22699
23275
|
async listConfigFiles() {
|
|
22700
23276
|
try {
|
|
22701
|
-
const entries = await
|
|
23277
|
+
const entries = await fs43.readdir(this.projectPath);
|
|
22702
23278
|
const configPatterns = [
|
|
22703
23279
|
/^package\.json$/,
|
|
22704
23280
|
/^Cargo\.toml$/,
|
|
@@ -22728,7 +23304,7 @@ var init_analyzer2 = __esm({
|
|
|
22728
23304
|
*/
|
|
22729
23305
|
async listDirectories() {
|
|
22730
23306
|
try {
|
|
22731
|
-
const entries = await
|
|
23307
|
+
const entries = await fs43.readdir(this.projectPath, { withFileTypes: true });
|
|
22732
23308
|
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => !name.startsWith(".") && name !== "node_modules");
|
|
22733
23309
|
} catch (error) {
|
|
22734
23310
|
if (isNotFoundError(error)) {
|
|
@@ -22799,7 +23375,7 @@ var init_analyzer2 = __esm({
|
|
|
22799
23375
|
*/
|
|
22800
23376
|
async fileExists(filename) {
|
|
22801
23377
|
try {
|
|
22802
|
-
await
|
|
23378
|
+
await fs43.access(path44.join(this.projectPath, filename));
|
|
22803
23379
|
return true;
|
|
22804
23380
|
} catch (error) {
|
|
22805
23381
|
if (isNotFoundError(error)) {
|
|
@@ -22813,8 +23389,8 @@ var init_analyzer2 = __esm({
|
|
|
22813
23389
|
*/
|
|
22814
23390
|
async readFile(relativePath) {
|
|
22815
23391
|
try {
|
|
22816
|
-
const fullPath =
|
|
22817
|
-
return await
|
|
23392
|
+
const fullPath = path44.join(this.projectPath, relativePath);
|
|
23393
|
+
return await fs43.readFile(fullPath, "utf-8");
|
|
22818
23394
|
} catch (error) {
|
|
22819
23395
|
if (isNotFoundError(error)) {
|
|
22820
23396
|
return null;
|
|
@@ -23062,8 +23638,8 @@ var analysis_exports = {};
|
|
|
23062
23638
|
__export(analysis_exports, {
|
|
23063
23639
|
AnalysisCommands: () => AnalysisCommands
|
|
23064
23640
|
});
|
|
23065
|
-
import
|
|
23066
|
-
import
|
|
23641
|
+
import fs44 from "node:fs/promises";
|
|
23642
|
+
import path45 from "node:path";
|
|
23067
23643
|
import prompts2 from "prompts";
|
|
23068
23644
|
var AnalysisCommands;
|
|
23069
23645
|
var init_analysis2 = __esm({
|
|
@@ -23152,7 +23728,7 @@ var init_analysis2 = __esm({
|
|
|
23152
23728
|
lines.push("# Repository Analysis\n");
|
|
23153
23729
|
lines.push(`Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
23154
23730
|
`);
|
|
23155
|
-
const projectName =
|
|
23731
|
+
const projectName = path45.basename(projectPath);
|
|
23156
23732
|
lines.push(`## Project: ${projectName}
|
|
23157
23733
|
`);
|
|
23158
23734
|
lines.push("## Stack Detected\n");
|
|
@@ -23292,10 +23868,10 @@ var init_analysis2 = __esm({
|
|
|
23292
23868
|
}
|
|
23293
23869
|
return { success: result2.success };
|
|
23294
23870
|
}
|
|
23295
|
-
const claudeMdPath =
|
|
23871
|
+
const claudeMdPath = path45.join(globalPath, "context", "CLAUDE.md");
|
|
23296
23872
|
let existingContent = null;
|
|
23297
23873
|
try {
|
|
23298
|
-
existingContent = await
|
|
23874
|
+
existingContent = await fs44.readFile(claudeMdPath, "utf-8");
|
|
23299
23875
|
} catch {
|
|
23300
23876
|
}
|
|
23301
23877
|
const isNonInteractive = !process.stdin.isTTY || options.json;
|
|
@@ -23317,7 +23893,7 @@ var init_analysis2 = __esm({
|
|
|
23317
23893
|
}
|
|
23318
23894
|
let newContent;
|
|
23319
23895
|
try {
|
|
23320
|
-
newContent = await
|
|
23896
|
+
newContent = await fs44.readFile(claudeMdPath, "utf-8");
|
|
23321
23897
|
} catch {
|
|
23322
23898
|
newContent = "";
|
|
23323
23899
|
}
|
|
@@ -23341,7 +23917,7 @@ var init_analysis2 = __esm({
|
|
|
23341
23917
|
}
|
|
23342
23918
|
const restoreOriginal = /* @__PURE__ */ __name(async () => {
|
|
23343
23919
|
if (existingContent != null) {
|
|
23344
|
-
await
|
|
23920
|
+
await fs44.writeFile(claudeMdPath, existingContent, "utf-8");
|
|
23345
23921
|
}
|
|
23346
23922
|
}, "restoreOriginal");
|
|
23347
23923
|
if (isNonInteractive) {
|
|
@@ -23563,7 +24139,7 @@ ${formatFullDiff(diff)}`);
|
|
|
23563
24139
|
let projectName = "Unknown";
|
|
23564
24140
|
try {
|
|
23565
24141
|
const projectJson = JSON.parse(
|
|
23566
|
-
await
|
|
24142
|
+
await fs44.readFile(path45.join(globalPath, "project.json"), "utf-8")
|
|
23567
24143
|
);
|
|
23568
24144
|
projectName = projectJson.name || "Unknown";
|
|
23569
24145
|
} catch {
|
|
@@ -23772,8 +24348,15 @@ ${formatFullDiff(diff)}`);
|
|
|
23772
24348
|
}
|
|
23773
24349
|
/**
|
|
23774
24350
|
* prjct verify - Verify integrity of sealed analysis (PRJ-263)
|
|
24351
|
+
*
|
|
24352
|
+
* Modes:
|
|
24353
|
+
* - Default: Cryptographic verification (signature check)
|
|
24354
|
+
* - --semantic: Semantic verification (data accuracy check, PRJ-270)
|
|
23775
24355
|
*/
|
|
23776
24356
|
async verify(projectPath = process.cwd(), options = {}) {
|
|
24357
|
+
if (options.semantic) {
|
|
24358
|
+
return this.semanticVerify(projectPath, options);
|
|
24359
|
+
}
|
|
23777
24360
|
try {
|
|
23778
24361
|
const initResult = await this.ensureProjectInit(projectPath);
|
|
23779
24362
|
if (!initResult.success) return initResult;
|
|
@@ -23799,6 +24382,72 @@ ${formatFullDiff(diff)}`);
|
|
|
23799
24382
|
return { success: false, error: errMsg };
|
|
23800
24383
|
}
|
|
23801
24384
|
}
|
|
24385
|
+
/**
|
|
24386
|
+
* prjct analysis verify --semantic - Semantic verification of analysis results (PRJ-270)
|
|
24387
|
+
*
|
|
24388
|
+
* Validates that analysis data matches actual project state:
|
|
24389
|
+
* - Frameworks exist in package.json
|
|
24390
|
+
* - Languages match file extensions
|
|
24391
|
+
* - Pattern locations reference real files
|
|
24392
|
+
* - File count is accurate
|
|
24393
|
+
* - Anti-pattern files exist
|
|
24394
|
+
*/
|
|
24395
|
+
async semanticVerify(projectPath = process.cwd(), options = {}) {
|
|
24396
|
+
try {
|
|
24397
|
+
const initResult = await this.ensureProjectInit(projectPath);
|
|
24398
|
+
if (!initResult.success) return initResult;
|
|
24399
|
+
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
24400
|
+
if (!projectId) {
|
|
24401
|
+
if (options.json) {
|
|
24402
|
+
console.log(JSON.stringify({ success: false, error: "No project ID found" }));
|
|
24403
|
+
} else {
|
|
24404
|
+
output_default.fail("No project ID found");
|
|
24405
|
+
}
|
|
24406
|
+
return { success: false, error: "No project ID found" };
|
|
24407
|
+
}
|
|
24408
|
+
const globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
24409
|
+
let repoPath = projectPath;
|
|
24410
|
+
try {
|
|
24411
|
+
const projectJson = JSON.parse(
|
|
24412
|
+
await fs44.readFile(path45.join(globalPath, "project.json"), "utf-8")
|
|
24413
|
+
);
|
|
24414
|
+
repoPath = projectJson.repoPath || projectPath;
|
|
24415
|
+
} catch {
|
|
24416
|
+
}
|
|
24417
|
+
const result = await analysisStorage.semanticVerify(projectId, repoPath);
|
|
24418
|
+
if (options.json) {
|
|
24419
|
+
console.log(JSON.stringify(result));
|
|
24420
|
+
return { success: result.passed, data: result };
|
|
24421
|
+
}
|
|
24422
|
+
console.log("");
|
|
24423
|
+
if (result.passed) {
|
|
24424
|
+
output_default.done("Semantic verification passed");
|
|
24425
|
+
console.log(
|
|
24426
|
+
` ${result.passedCount}/${result.checks.length} checks passed (${result.totalMs}ms)`
|
|
24427
|
+
);
|
|
24428
|
+
} else {
|
|
24429
|
+
output_default.fail("Semantic verification failed");
|
|
24430
|
+
console.log(` ${result.failedCount}/${result.checks.length} checks failed`);
|
|
24431
|
+
}
|
|
24432
|
+
console.log("");
|
|
24433
|
+
console.log("Check Results:");
|
|
24434
|
+
for (const check of result.checks) {
|
|
24435
|
+
const icon = check.passed ? "\u2713" : "\u2717";
|
|
24436
|
+
const status = check.passed ? `${check.output} (${check.durationMs}ms)` : check.error || "Failed";
|
|
24437
|
+
console.log(` ${icon} ${check.name}: ${status}`);
|
|
24438
|
+
}
|
|
24439
|
+
console.log("");
|
|
24440
|
+
return { success: result.passed, data: result };
|
|
24441
|
+
} catch (error) {
|
|
24442
|
+
const errMsg = getErrorMessage2(error);
|
|
24443
|
+
if (options.json) {
|
|
24444
|
+
console.log(JSON.stringify({ success: false, error: errMsg }));
|
|
24445
|
+
} else {
|
|
24446
|
+
output_default.fail(errMsg);
|
|
24447
|
+
}
|
|
24448
|
+
return { success: false, error: errMsg };
|
|
24449
|
+
}
|
|
24450
|
+
}
|
|
23802
24451
|
/**
|
|
23803
24452
|
* Get session activity stats from today's events
|
|
23804
24453
|
* @see PRJ-89
|
|
@@ -23954,7 +24603,7 @@ var planning_exports = {};
|
|
|
23954
24603
|
__export(planning_exports, {
|
|
23955
24604
|
PlanningCommands: () => PlanningCommands
|
|
23956
24605
|
});
|
|
23957
|
-
import
|
|
24606
|
+
import path46 from "node:path";
|
|
23958
24607
|
async function getAnalysisCommands() {
|
|
23959
24608
|
if (!_analysisCommands) {
|
|
23960
24609
|
const { AnalysisCommands: AnalysisCommands2 } = await Promise.resolve().then(() => (init_analysis2(), analysis_exports));
|
|
@@ -24062,7 +24711,7 @@ var init_planning = __esm({
|
|
|
24062
24711
|
);
|
|
24063
24712
|
}
|
|
24064
24713
|
for (const [filePath, content] of Object.entries(baseFiles)) {
|
|
24065
|
-
await tool_registry_default.get("Write")(
|
|
24714
|
+
await tool_registry_default.get("Write")(path46.join(globalPath, filePath), content);
|
|
24066
24715
|
}
|
|
24067
24716
|
const isEmpty = await this._detectEmptyDirectory(projectPath);
|
|
24068
24717
|
const hasCode = await this._detectExistingCode(projectPath);
|
|
@@ -24089,7 +24738,7 @@ var init_planning = __esm({
|
|
|
24089
24738
|
return { success: true, mode: "blank_no_idea", projectId, wizard: wizardResult };
|
|
24090
24739
|
}
|
|
24091
24740
|
output_default.spin("architect mode...");
|
|
24092
|
-
const sessionPath =
|
|
24741
|
+
const sessionPath = path46.join(globalPath, "planning", "architect-session.md");
|
|
24093
24742
|
const sessionContent = `# Architect Session
|
|
24094
24743
|
|
|
24095
24744
|
## Idea
|
|
@@ -24275,7 +24924,7 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
|
24275
24924
|
if (!initResult.success) return initResult;
|
|
24276
24925
|
console.log("\u{1F3D7}\uFE0F Architect Mode - Code Generation\n");
|
|
24277
24926
|
const globalPath = await this.getGlobalProjectPath(projectPath);
|
|
24278
|
-
const planPath =
|
|
24927
|
+
const planPath = path46.join(globalPath, "planning", "architect-session.md");
|
|
24279
24928
|
let planContent;
|
|
24280
24929
|
try {
|
|
24281
24930
|
planContent = await file_helper_exports.readFile(planPath);
|
|
@@ -24350,7 +24999,7 @@ ${"=".repeat(60)}`);
|
|
|
24350
24999
|
if (isComplex) {
|
|
24351
25000
|
output_default.spin("analyzing idea...");
|
|
24352
25001
|
const globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
24353
|
-
const sessionPath =
|
|
25002
|
+
const sessionPath = path46.join(globalPath, "planning", "architect-session.md");
|
|
24354
25003
|
const sessionContent = `# Architect Session
|
|
24355
25004
|
|
|
24356
25005
|
## Idea
|
|
@@ -24406,10 +25055,10 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
|
24406
25055
|
if (!featureName) {
|
|
24407
25056
|
output_default.spin("loading specs...");
|
|
24408
25057
|
const globalPath2 = path_manager_default.getGlobalProjectPath(projectId);
|
|
24409
|
-
const specsPath2 =
|
|
25058
|
+
const specsPath2 = path46.join(globalPath2, "planning", "specs");
|
|
24410
25059
|
try {
|
|
24411
|
-
const
|
|
24412
|
-
const files = await
|
|
25060
|
+
const fs62 = await import("node:fs/promises");
|
|
25061
|
+
const files = await fs62.readdir(specsPath2);
|
|
24413
25062
|
const specs = files.filter((f) => f.endsWith(".md") && f !== ".gitkeep");
|
|
24414
25063
|
if (specs.length === 0) {
|
|
24415
25064
|
output_default.warn("no specs yet");
|
|
@@ -24432,10 +25081,10 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
|
24432
25081
|
}
|
|
24433
25082
|
output_default.spin("creating spec...");
|
|
24434
25083
|
const globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
24435
|
-
const specsPath =
|
|
25084
|
+
const specsPath = path46.join(globalPath, "planning", "specs");
|
|
24436
25085
|
await file_helper_exports.ensureDir(specsPath);
|
|
24437
25086
|
const slug = featureName.toLowerCase().replace(/\s+/g, "-");
|
|
24438
|
-
const specFile =
|
|
25087
|
+
const specFile = path46.join(specsPath, `${slug}.md`);
|
|
24439
25088
|
const specContent = `# Specification: ${featureName}
|
|
24440
25089
|
|
|
24441
25090
|
## Overview
|
|
@@ -24623,8 +25272,8 @@ var init_project_service = __esm({
|
|
|
24623
25272
|
|
|
24624
25273
|
// core/services/staleness-checker.ts
|
|
24625
25274
|
import { exec as exec12 } from "node:child_process";
|
|
24626
|
-
import
|
|
24627
|
-
import
|
|
25275
|
+
import fs45 from "node:fs/promises";
|
|
25276
|
+
import path47 from "node:path";
|
|
24628
25277
|
import { promisify as promisify13 } from "node:util";
|
|
24629
25278
|
var execAsync8, DEFAULT_CONFIG, StalenessChecker, createStalenessChecker;
|
|
24630
25279
|
var init_staleness_checker = __esm({
|
|
@@ -24674,10 +25323,10 @@ var init_staleness_checker = __esm({
|
|
|
24674
25323
|
significantChanges: []
|
|
24675
25324
|
};
|
|
24676
25325
|
try {
|
|
24677
|
-
const projectJsonPath =
|
|
25326
|
+
const projectJsonPath = path47.join(path_manager_default.getGlobalProjectPath(projectId), "project.json");
|
|
24678
25327
|
let projectJson = {};
|
|
24679
25328
|
try {
|
|
24680
|
-
projectJson = JSON.parse(await
|
|
25329
|
+
projectJson = JSON.parse(await fs45.readFile(projectJsonPath, "utf-8"));
|
|
24681
25330
|
} catch {
|
|
24682
25331
|
status.isStale = true;
|
|
24683
25332
|
status.reason = "No sync history found. Run `prjct sync` to initialize.";
|
|
@@ -25139,7 +25788,7 @@ var init_formatters = __esm({
|
|
|
25139
25788
|
// core/ai-tools/registry.ts
|
|
25140
25789
|
import { exec as exec13 } from "node:child_process";
|
|
25141
25790
|
import os13 from "node:os";
|
|
25142
|
-
import
|
|
25791
|
+
import path48 from "node:path";
|
|
25143
25792
|
import { promisify as promisify14 } from "node:util";
|
|
25144
25793
|
function getAIToolConfig(id) {
|
|
25145
25794
|
return AI_TOOLS[id] || null;
|
|
@@ -25157,16 +25806,16 @@ async function detectInstalledTools(repoPath = process.cwd()) {
|
|
|
25157
25806
|
if (await commandExists("claude")) {
|
|
25158
25807
|
detected.push("claude");
|
|
25159
25808
|
}
|
|
25160
|
-
if (await commandExists("cursor") || await fileExists(
|
|
25809
|
+
if (await commandExists("cursor") || await fileExists(path48.join(repoPath, ".cursor"))) {
|
|
25161
25810
|
detected.push("cursor");
|
|
25162
25811
|
}
|
|
25163
|
-
if (await fileExists(
|
|
25812
|
+
if (await fileExists(path48.join(repoPath, ".github"))) {
|
|
25164
25813
|
detected.push("copilot");
|
|
25165
25814
|
}
|
|
25166
|
-
if (await commandExists("windsurf") || await fileExists(
|
|
25815
|
+
if (await commandExists("windsurf") || await fileExists(path48.join(repoPath, ".windsurf"))) {
|
|
25167
25816
|
detected.push("windsurf");
|
|
25168
25817
|
}
|
|
25169
|
-
if (await fileExists(
|
|
25818
|
+
if (await fileExists(path48.join(repoPath, ".continue")) || await fileExists(path48.join(os13.homedir(), ".continue"))) {
|
|
25170
25819
|
detected.push("continue");
|
|
25171
25820
|
}
|
|
25172
25821
|
return detected;
|
|
@@ -25244,8 +25893,8 @@ var init_registry = __esm({
|
|
|
25244
25893
|
});
|
|
25245
25894
|
|
|
25246
25895
|
// core/ai-tools/generator.ts
|
|
25247
|
-
import
|
|
25248
|
-
import
|
|
25896
|
+
import fs46 from "node:fs/promises";
|
|
25897
|
+
import path49 from "node:path";
|
|
25249
25898
|
async function generateAIToolContexts(context2, globalPath, repoPath, toolIds = DEFAULT_AI_TOOLS) {
|
|
25250
25899
|
const results = [];
|
|
25251
25900
|
for (const toolId of toolIds) {
|
|
@@ -25280,13 +25929,13 @@ async function generateForTool(context2, config, globalPath, repoPath) {
|
|
|
25280
25929
|
let content = formatter(context2, config);
|
|
25281
25930
|
let outputPath;
|
|
25282
25931
|
if (config.outputPath === "repo") {
|
|
25283
|
-
outputPath =
|
|
25932
|
+
outputPath = path49.join(repoPath, config.outputFile);
|
|
25284
25933
|
} else {
|
|
25285
|
-
outputPath =
|
|
25934
|
+
outputPath = path49.join(globalPath, "context", config.outputFile);
|
|
25286
25935
|
}
|
|
25287
|
-
await
|
|
25936
|
+
await fs46.mkdir(path49.dirname(outputPath), { recursive: true });
|
|
25288
25937
|
try {
|
|
25289
|
-
const existingContent = await
|
|
25938
|
+
const existingContent = await fs46.readFile(outputPath, "utf-8");
|
|
25290
25939
|
const validation = validatePreserveBlocks(existingContent);
|
|
25291
25940
|
if (!validation.valid) {
|
|
25292
25941
|
console.warn(`\u26A0\uFE0F ${config.outputFile} has invalid preserve blocks:`);
|
|
@@ -25297,7 +25946,7 @@ async function generateForTool(context2, config, globalPath, repoPath) {
|
|
|
25297
25946
|
content = mergePreservedSections(content, existingContent);
|
|
25298
25947
|
} catch {
|
|
25299
25948
|
}
|
|
25300
|
-
await
|
|
25949
|
+
await fs46.writeFile(outputPath, content, "utf-8");
|
|
25301
25950
|
return {
|
|
25302
25951
|
toolId: config.id,
|
|
25303
25952
|
outputFile: config.outputFile,
|
|
@@ -25337,8 +25986,8 @@ var init_ai_tools = __esm({
|
|
|
25337
25986
|
});
|
|
25338
25987
|
|
|
25339
25988
|
// core/domain/bm25.ts
|
|
25340
|
-
import
|
|
25341
|
-
import
|
|
25989
|
+
import fs47 from "node:fs/promises";
|
|
25990
|
+
import path50 from "node:path";
|
|
25342
25991
|
function splitIdentifier(identifier) {
|
|
25343
25992
|
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);
|
|
25344
25993
|
}
|
|
@@ -25405,16 +26054,16 @@ function tokenizeFile(content, filePath) {
|
|
|
25405
26054
|
}
|
|
25406
26055
|
async function listFiles2(dir, projectPath) {
|
|
25407
26056
|
const files = [];
|
|
25408
|
-
const entries = await
|
|
26057
|
+
const entries = await fs47.readdir(dir, { withFileTypes: true });
|
|
25409
26058
|
for (const entry of entries) {
|
|
25410
26059
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
25411
|
-
const fullPath =
|
|
26060
|
+
const fullPath = path50.join(dir, entry.name);
|
|
25412
26061
|
if (entry.isDirectory()) {
|
|
25413
26062
|
files.push(...await listFiles2(fullPath, projectPath));
|
|
25414
26063
|
} else if (entry.isFile()) {
|
|
25415
|
-
const ext =
|
|
26064
|
+
const ext = path50.extname(entry.name).toLowerCase();
|
|
25416
26065
|
if (INDEXABLE_EXTENSIONS.has(ext)) {
|
|
25417
|
-
files.push(
|
|
26066
|
+
files.push(path50.relative(projectPath, fullPath));
|
|
25418
26067
|
}
|
|
25419
26068
|
}
|
|
25420
26069
|
}
|
|
@@ -25431,7 +26080,7 @@ async function buildIndex(projectPath) {
|
|
|
25431
26080
|
const results = await Promise.all(
|
|
25432
26081
|
batch.map(async (filePath) => {
|
|
25433
26082
|
try {
|
|
25434
|
-
const content = await
|
|
26083
|
+
const content = await fs47.readFile(path50.join(projectPath, filePath), "utf-8");
|
|
25435
26084
|
const tokens = tokenizeFile(content, filePath);
|
|
25436
26085
|
return { filePath, tokens };
|
|
25437
26086
|
} catch {
|
|
@@ -25609,8 +26258,8 @@ var init_bm25 = __esm({
|
|
|
25609
26258
|
});
|
|
25610
26259
|
|
|
25611
26260
|
// core/domain/import-graph.ts
|
|
25612
|
-
import
|
|
25613
|
-
import
|
|
26261
|
+
import fs48 from "node:fs/promises";
|
|
26262
|
+
import path51 from "node:path";
|
|
25614
26263
|
function extractImportSources(content) {
|
|
25615
26264
|
const sources = [];
|
|
25616
26265
|
let match;
|
|
@@ -25626,17 +26275,17 @@ function extractImportSources(content) {
|
|
|
25626
26275
|
async function resolveImport2(source, fromFile, projectPath) {
|
|
25627
26276
|
let basePath;
|
|
25628
26277
|
if (source.startsWith("@/")) {
|
|
25629
|
-
basePath =
|
|
26278
|
+
basePath = path51.join(projectPath, "src", source.slice(2));
|
|
25630
26279
|
} else {
|
|
25631
|
-
const fromDir =
|
|
25632
|
-
basePath =
|
|
26280
|
+
const fromDir = path51.dirname(path51.join(projectPath, fromFile));
|
|
26281
|
+
basePath = path51.resolve(fromDir, source);
|
|
25633
26282
|
}
|
|
25634
26283
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
25635
26284
|
const fullPath = basePath + ext;
|
|
25636
26285
|
try {
|
|
25637
|
-
const stat = await
|
|
26286
|
+
const stat = await fs48.stat(fullPath);
|
|
25638
26287
|
if (stat.isFile()) {
|
|
25639
|
-
return
|
|
26288
|
+
return path51.relative(projectPath, fullPath);
|
|
25640
26289
|
}
|
|
25641
26290
|
} catch {
|
|
25642
26291
|
}
|
|
@@ -25645,16 +26294,16 @@ async function resolveImport2(source, fromFile, projectPath) {
|
|
|
25645
26294
|
}
|
|
25646
26295
|
async function listFiles3(dir, projectPath) {
|
|
25647
26296
|
const files = [];
|
|
25648
|
-
const entries = await
|
|
26297
|
+
const entries = await fs48.readdir(dir, { withFileTypes: true });
|
|
25649
26298
|
for (const entry of entries) {
|
|
25650
26299
|
if (SKIP_DIRS2.has(entry.name)) continue;
|
|
25651
|
-
const fullPath =
|
|
26300
|
+
const fullPath = path51.join(dir, entry.name);
|
|
25652
26301
|
if (entry.isDirectory()) {
|
|
25653
26302
|
files.push(...await listFiles3(fullPath, projectPath));
|
|
25654
26303
|
} else if (entry.isFile()) {
|
|
25655
|
-
const ext =
|
|
26304
|
+
const ext = path51.extname(entry.name).toLowerCase();
|
|
25656
26305
|
if (INDEXABLE_EXTENSIONS2.has(ext)) {
|
|
25657
|
-
files.push(
|
|
26306
|
+
files.push(path51.relative(projectPath, fullPath));
|
|
25658
26307
|
}
|
|
25659
26308
|
}
|
|
25660
26309
|
}
|
|
@@ -25671,7 +26320,7 @@ async function buildGraph(projectPath) {
|
|
|
25671
26320
|
const results = await Promise.all(
|
|
25672
26321
|
batch.map(async (filePath) => {
|
|
25673
26322
|
try {
|
|
25674
|
-
const content = await
|
|
26323
|
+
const content = await fs48.readFile(path51.join(projectPath, filePath), "utf-8");
|
|
25675
26324
|
const sources = extractImportSources(content);
|
|
25676
26325
|
const resolved = [];
|
|
25677
26326
|
for (const source of sources) {
|
|
@@ -25806,22 +26455,22 @@ var init_change_propagator = __esm({
|
|
|
25806
26455
|
});
|
|
25807
26456
|
|
|
25808
26457
|
// core/domain/file-hasher.ts
|
|
25809
|
-
import
|
|
25810
|
-
import
|
|
26458
|
+
import fs49 from "node:fs/promises";
|
|
26459
|
+
import path52 from "node:path";
|
|
25811
26460
|
async function listProjectFiles(dir, projectPath) {
|
|
25812
26461
|
const files = [];
|
|
25813
|
-
const entries = await
|
|
26462
|
+
const entries = await fs49.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
25814
26463
|
for (const entry of entries) {
|
|
25815
26464
|
const name = String(entry.name);
|
|
25816
26465
|
if (SKIP_DIRS3.has(name)) continue;
|
|
25817
26466
|
if (name.startsWith(".") && name !== ".env.example") continue;
|
|
25818
|
-
const fullPath =
|
|
26467
|
+
const fullPath = path52.join(dir, name);
|
|
25819
26468
|
if (entry.isDirectory()) {
|
|
25820
26469
|
files.push(...await listProjectFiles(fullPath, projectPath));
|
|
25821
26470
|
} else if (entry.isFile()) {
|
|
25822
|
-
const ext =
|
|
26471
|
+
const ext = path52.extname(name).toLowerCase();
|
|
25823
26472
|
if (INDEXABLE_EXTENSIONS3.has(ext)) {
|
|
25824
|
-
files.push(
|
|
26473
|
+
files.push(path52.relative(projectPath, fullPath));
|
|
25825
26474
|
}
|
|
25826
26475
|
}
|
|
25827
26476
|
}
|
|
@@ -25847,10 +26496,10 @@ async function computeHashes(projectPath) {
|
|
|
25847
26496
|
const results = await Promise.all(
|
|
25848
26497
|
batch.map(async (filePath) => {
|
|
25849
26498
|
try {
|
|
25850
|
-
const fullPath =
|
|
26499
|
+
const fullPath = path52.join(projectPath, filePath);
|
|
25851
26500
|
const [content, stat] = await Promise.all([
|
|
25852
|
-
|
|
25853
|
-
|
|
26501
|
+
fs49.readFile(fullPath, "utf-8"),
|
|
26502
|
+
fs49.stat(fullPath)
|
|
25854
26503
|
]);
|
|
25855
26504
|
return {
|
|
25856
26505
|
path: filePath,
|
|
@@ -26093,8 +26742,8 @@ var init_git_cochange = __esm({
|
|
|
26093
26742
|
});
|
|
26094
26743
|
|
|
26095
26744
|
// core/services/context-generator.ts
|
|
26096
|
-
import
|
|
26097
|
-
import
|
|
26745
|
+
import fs50 from "node:fs/promises";
|
|
26746
|
+
import path53 from "node:path";
|
|
26098
26747
|
var ContextFileGenerator;
|
|
26099
26748
|
var init_context_generator = __esm({
|
|
26100
26749
|
"core/services/context-generator.ts"() {
|
|
@@ -26119,10 +26768,10 @@ var init_context_generator = __esm({
|
|
|
26119
26768
|
async writeWithPreservation(filePath, content) {
|
|
26120
26769
|
let finalContent = content;
|
|
26121
26770
|
try {
|
|
26122
|
-
const existingContent = await
|
|
26771
|
+
const existingContent = await fs50.readFile(filePath, "utf-8");
|
|
26123
26772
|
const validation = validatePreserveBlocks(existingContent);
|
|
26124
26773
|
if (!validation.valid) {
|
|
26125
|
-
const filename =
|
|
26774
|
+
const filename = path53.basename(filePath);
|
|
26126
26775
|
console.warn(`\u26A0\uFE0F ${filename} has invalid preserve blocks:`);
|
|
26127
26776
|
for (const error of validation.errors) {
|
|
26128
26777
|
console.warn(` ${error}`);
|
|
@@ -26131,13 +26780,13 @@ var init_context_generator = __esm({
|
|
|
26131
26780
|
finalContent = mergePreservedSections(content, existingContent);
|
|
26132
26781
|
} catch {
|
|
26133
26782
|
}
|
|
26134
|
-
await
|
|
26783
|
+
await fs50.writeFile(filePath, finalContent, "utf-8");
|
|
26135
26784
|
}
|
|
26136
26785
|
/**
|
|
26137
26786
|
* Generate all context files in parallel
|
|
26138
26787
|
*/
|
|
26139
26788
|
async generate(git, stats, commands, agents, sources) {
|
|
26140
|
-
const contextPath =
|
|
26789
|
+
const contextPath = path53.join(this.config.globalPath, "context");
|
|
26141
26790
|
await Promise.all([
|
|
26142
26791
|
this.generateClaudeMd(contextPath, git, stats, commands, agents, sources),
|
|
26143
26792
|
this.generateNowMd(contextPath),
|
|
@@ -26237,7 +26886,7 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
|
|
|
26237
26886
|
**Workflow**: ${workflowAgents.join(", ")}
|
|
26238
26887
|
**Domain**: ${domainAgents.join(", ") || "none"}
|
|
26239
26888
|
`;
|
|
26240
|
-
const claudePath =
|
|
26889
|
+
const claudePath = path53.join(contextPath, "CLAUDE.md");
|
|
26241
26890
|
await this.writeWithPreservation(claudePath, content);
|
|
26242
26891
|
}
|
|
26243
26892
|
/**
|
|
@@ -26246,8 +26895,8 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
|
|
|
26246
26895
|
async generateNowMd(contextPath) {
|
|
26247
26896
|
let currentTask = null;
|
|
26248
26897
|
try {
|
|
26249
|
-
const statePath =
|
|
26250
|
-
const state = JSON.parse(await
|
|
26898
|
+
const statePath = path53.join(this.config.globalPath, "storage", "state.json");
|
|
26899
|
+
const state = JSON.parse(await fs50.readFile(statePath, "utf-8"));
|
|
26251
26900
|
currentTask = state.currentTask;
|
|
26252
26901
|
} catch {
|
|
26253
26902
|
}
|
|
@@ -26263,7 +26912,7 @@ _No active task_
|
|
|
26263
26912
|
|
|
26264
26913
|
Use \`p. task "description"\` to start working.
|
|
26265
26914
|
`;
|
|
26266
|
-
await this.writeWithPreservation(
|
|
26915
|
+
await this.writeWithPreservation(path53.join(contextPath, "now.md"), content);
|
|
26267
26916
|
}
|
|
26268
26917
|
/**
|
|
26269
26918
|
* Generate next.md - task queue
|
|
@@ -26271,15 +26920,15 @@ Use \`p. task "description"\` to start working.
|
|
|
26271
26920
|
async generateNextMd(contextPath) {
|
|
26272
26921
|
let queue = { tasks: [] };
|
|
26273
26922
|
try {
|
|
26274
|
-
const queuePath =
|
|
26275
|
-
queue = JSON.parse(await
|
|
26923
|
+
const queuePath = path53.join(this.config.globalPath, "storage", "queue.json");
|
|
26924
|
+
queue = JSON.parse(await fs50.readFile(queuePath, "utf-8"));
|
|
26276
26925
|
} catch {
|
|
26277
26926
|
}
|
|
26278
26927
|
const content = `# NEXT
|
|
26279
26928
|
|
|
26280
26929
|
${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ""}`).join("\n") : "_Empty queue_"}
|
|
26281
26930
|
`;
|
|
26282
|
-
await this.writeWithPreservation(
|
|
26931
|
+
await this.writeWithPreservation(path53.join(contextPath, "next.md"), content);
|
|
26283
26932
|
}
|
|
26284
26933
|
/**
|
|
26285
26934
|
* Generate ideas.md - captured ideas
|
|
@@ -26287,15 +26936,15 @@ ${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}
|
|
|
26287
26936
|
async generateIdeasMd(contextPath) {
|
|
26288
26937
|
let ideas = { ideas: [] };
|
|
26289
26938
|
try {
|
|
26290
|
-
const ideasPath =
|
|
26291
|
-
ideas = JSON.parse(await
|
|
26939
|
+
const ideasPath = path53.join(this.config.globalPath, "storage", "ideas.json");
|
|
26940
|
+
ideas = JSON.parse(await fs50.readFile(ideasPath, "utf-8"));
|
|
26292
26941
|
} catch {
|
|
26293
26942
|
}
|
|
26294
26943
|
const content = `# IDEAS
|
|
26295
26944
|
|
|
26296
26945
|
${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [${i.priority}]` : ""}`).join("\n") : "_No ideas captured yet_"}
|
|
26297
26946
|
`;
|
|
26298
|
-
await this.writeWithPreservation(
|
|
26947
|
+
await this.writeWithPreservation(path53.join(contextPath, "ideas.md"), content);
|
|
26299
26948
|
}
|
|
26300
26949
|
/**
|
|
26301
26950
|
* Generate shipped.md - completed features
|
|
@@ -26305,8 +26954,8 @@ ${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [
|
|
|
26305
26954
|
shipped: []
|
|
26306
26955
|
};
|
|
26307
26956
|
try {
|
|
26308
|
-
const shippedPath =
|
|
26309
|
-
shipped = JSON.parse(await
|
|
26957
|
+
const shippedPath = path53.join(this.config.globalPath, "storage", "shipped.json");
|
|
26958
|
+
shipped = JSON.parse(await fs50.readFile(shippedPath, "utf-8"));
|
|
26310
26959
|
} catch {
|
|
26311
26960
|
}
|
|
26312
26961
|
const content = `# SHIPPED \u{1F680}
|
|
@@ -26315,7 +26964,7 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
|
|
|
26315
26964
|
|
|
26316
26965
|
**Total shipped:** ${shipped.shipped.length}
|
|
26317
26966
|
`;
|
|
26318
|
-
await this.writeWithPreservation(
|
|
26967
|
+
await this.writeWithPreservation(path53.join(contextPath, "shipped.md"), content);
|
|
26319
26968
|
}
|
|
26320
26969
|
// ==========================================================================
|
|
26321
26970
|
// MONOREPO SUPPORT
|
|
@@ -26344,9 +26993,9 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
|
|
|
26344
26993
|
commands,
|
|
26345
26994
|
agents
|
|
26346
26995
|
);
|
|
26347
|
-
const claudePath =
|
|
26996
|
+
const claudePath = path53.join(pkg.path, "CLAUDE.md");
|
|
26348
26997
|
await this.writeWithPreservation(claudePath, content);
|
|
26349
|
-
generatedFiles.push(
|
|
26998
|
+
generatedFiles.push(path53.relative(this.config.projectPath, claudePath));
|
|
26350
26999
|
}
|
|
26351
27000
|
return generatedFiles;
|
|
26352
27001
|
}
|
|
@@ -26359,8 +27008,8 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
|
|
|
26359
27008
|
let pkgVersion = stats.version;
|
|
26360
27009
|
let pkgName = pkg.name;
|
|
26361
27010
|
try {
|
|
26362
|
-
const pkgJsonPath =
|
|
26363
|
-
const pkgJson = JSON.parse(await
|
|
27011
|
+
const pkgJsonPath = path53.join(pkg.path, "package.json");
|
|
27012
|
+
const pkgJson = JSON.parse(await fs50.readFile(pkgJsonPath, "utf-8"));
|
|
26364
27013
|
pkgVersion = pkgJson.version || stats.version;
|
|
26365
27014
|
pkgName = pkgJson.name || pkg.name;
|
|
26366
27015
|
} catch {
|
|
@@ -26425,8 +27074,8 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
|
|
|
26425
27074
|
});
|
|
26426
27075
|
|
|
26427
27076
|
// core/services/local-state-generator.ts
|
|
26428
|
-
import
|
|
26429
|
-
import
|
|
27077
|
+
import fs51 from "node:fs/promises";
|
|
27078
|
+
import path54 from "node:path";
|
|
26430
27079
|
var LOCAL_STATE_FILENAME, LocalStateGenerator, localStateGenerator;
|
|
26431
27080
|
var init_local_state_generator = __esm({
|
|
26432
27081
|
"core/services/local-state-generator.ts"() {
|
|
@@ -26441,17 +27090,17 @@ var init_local_state_generator = __esm({
|
|
|
26441
27090
|
* Generate .prjct-state.md in the project root
|
|
26442
27091
|
*/
|
|
26443
27092
|
async generate(projectPath, state) {
|
|
26444
|
-
const filePath =
|
|
27093
|
+
const filePath = path54.join(projectPath, LOCAL_STATE_FILENAME);
|
|
26445
27094
|
const content = this.toMarkdown(state);
|
|
26446
|
-
await
|
|
27095
|
+
await fs51.writeFile(filePath, content, "utf-8");
|
|
26447
27096
|
}
|
|
26448
27097
|
/**
|
|
26449
27098
|
* Remove local state file
|
|
26450
27099
|
*/
|
|
26451
27100
|
async remove(projectPath) {
|
|
26452
|
-
const filePath =
|
|
27101
|
+
const filePath = path54.join(projectPath, LOCAL_STATE_FILENAME);
|
|
26453
27102
|
try {
|
|
26454
|
-
await
|
|
27103
|
+
await fs51.unlink(filePath);
|
|
26455
27104
|
} catch (error) {
|
|
26456
27105
|
if (!isNotFoundError(error)) throw error;
|
|
26457
27106
|
}
|
|
@@ -26460,9 +27109,9 @@ var init_local_state_generator = __esm({
|
|
|
26460
27109
|
* Check if local state file exists
|
|
26461
27110
|
*/
|
|
26462
27111
|
async exists(projectPath) {
|
|
26463
|
-
const filePath =
|
|
27112
|
+
const filePath = path54.join(projectPath, LOCAL_STATE_FILENAME);
|
|
26464
27113
|
try {
|
|
26465
|
-
await
|
|
27114
|
+
await fs51.access(filePath);
|
|
26466
27115
|
return true;
|
|
26467
27116
|
} catch {
|
|
26468
27117
|
return false;
|
|
@@ -26541,11 +27190,11 @@ var init_local_state_generator = __esm({
|
|
|
26541
27190
|
});
|
|
26542
27191
|
|
|
26543
27192
|
// core/services/skill-lock.ts
|
|
26544
|
-
import
|
|
27193
|
+
import fs52 from "node:fs/promises";
|
|
26545
27194
|
import os14 from "node:os";
|
|
26546
|
-
import
|
|
27195
|
+
import path55 from "node:path";
|
|
26547
27196
|
function getLockFilePath() {
|
|
26548
|
-
return
|
|
27197
|
+
return path55.join(os14.homedir(), ".prjct-cli", "skills", LOCK_FILE_NAME);
|
|
26549
27198
|
}
|
|
26550
27199
|
function createEmptyLockFile() {
|
|
26551
27200
|
return {
|
|
@@ -26556,7 +27205,7 @@ function createEmptyLockFile() {
|
|
|
26556
27205
|
}
|
|
26557
27206
|
async function read() {
|
|
26558
27207
|
try {
|
|
26559
|
-
const content = await
|
|
27208
|
+
const content = await fs52.readFile(getLockFilePath(), "utf-8");
|
|
26560
27209
|
return JSON.parse(content);
|
|
26561
27210
|
} catch {
|
|
26562
27211
|
return createEmptyLockFile();
|
|
@@ -26564,9 +27213,9 @@ async function read() {
|
|
|
26564
27213
|
}
|
|
26565
27214
|
async function write(lockFile) {
|
|
26566
27215
|
const lockPath = getLockFilePath();
|
|
26567
|
-
await
|
|
27216
|
+
await fs52.mkdir(path55.dirname(lockPath), { recursive: true });
|
|
26568
27217
|
lockFile.generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
26569
|
-
await
|
|
27218
|
+
await fs52.writeFile(lockPath, JSON.stringify(lockFile, null, 2), "utf-8");
|
|
26570
27219
|
}
|
|
26571
27220
|
async function addEntry(entry) {
|
|
26572
27221
|
const lockFile = await read();
|
|
@@ -26619,14 +27268,14 @@ var init_skill_lock = __esm({
|
|
|
26619
27268
|
|
|
26620
27269
|
// core/services/skill-installer.ts
|
|
26621
27270
|
import { exec as execCallback8 } from "node:child_process";
|
|
26622
|
-
import
|
|
27271
|
+
import fs53 from "node:fs/promises";
|
|
26623
27272
|
import os15 from "node:os";
|
|
26624
|
-
import
|
|
27273
|
+
import path56 from "node:path";
|
|
26625
27274
|
import { promisify as promisify16 } from "node:util";
|
|
26626
27275
|
import { glob } from "glob";
|
|
26627
27276
|
function parseSource(source) {
|
|
26628
27277
|
if (source.startsWith("./") || source.startsWith("/") || source.startsWith("~")) {
|
|
26629
|
-
const resolvedPath = source.startsWith("~") ?
|
|
27278
|
+
const resolvedPath = source.startsWith("~") ? path56.join(os15.homedir(), source.slice(1)) : path56.resolve(source);
|
|
26630
27279
|
return {
|
|
26631
27280
|
type: "local",
|
|
26632
27281
|
localPath: resolvedPath,
|
|
@@ -26664,22 +27313,22 @@ function parseSource(source) {
|
|
|
26664
27313
|
async function discoverSkills(dir) {
|
|
26665
27314
|
const skills = [];
|
|
26666
27315
|
try {
|
|
26667
|
-
const rootSkill =
|
|
26668
|
-
await
|
|
26669
|
-
const dirName =
|
|
27316
|
+
const rootSkill = path56.join(dir, "SKILL.md");
|
|
27317
|
+
await fs53.access(rootSkill);
|
|
27318
|
+
const dirName = path56.basename(dir);
|
|
26670
27319
|
skills.push({ name: dirName, filePath: rootSkill });
|
|
26671
27320
|
} catch {
|
|
26672
27321
|
}
|
|
26673
27322
|
const subdirSkills = await glob("*/SKILL.md", { cwd: dir, absolute: true });
|
|
26674
27323
|
for (const filePath of subdirSkills) {
|
|
26675
|
-
const name =
|
|
27324
|
+
const name = path56.basename(path56.dirname(filePath));
|
|
26676
27325
|
if (!skills.some((s) => s.name === name)) {
|
|
26677
27326
|
skills.push({ name, filePath });
|
|
26678
27327
|
}
|
|
26679
27328
|
}
|
|
26680
27329
|
const nestedSkills = await glob("skills/*/SKILL.md", { cwd: dir, absolute: true });
|
|
26681
27330
|
for (const filePath of nestedSkills) {
|
|
26682
|
-
const name =
|
|
27331
|
+
const name = path56.basename(path56.dirname(filePath));
|
|
26683
27332
|
if (!skills.some((s) => s.name === name)) {
|
|
26684
27333
|
skills.push({ name, filePath });
|
|
26685
27334
|
}
|
|
@@ -26715,16 +27364,16 @@ ${prjctBlock.join("\n")}
|
|
|
26715
27364
|
${content}`;
|
|
26716
27365
|
}
|
|
26717
27366
|
function getInstallDir() {
|
|
26718
|
-
return
|
|
27367
|
+
return path56.join(os15.homedir(), ".claude", "skills");
|
|
26719
27368
|
}
|
|
26720
27369
|
async function installSkillFile(sourcePath, name, source, sha) {
|
|
26721
27370
|
const installDir = getInstallDir();
|
|
26722
|
-
const targetDir =
|
|
26723
|
-
const targetPath =
|
|
26724
|
-
const content = await
|
|
27371
|
+
const targetDir = path56.join(installDir, name);
|
|
27372
|
+
const targetPath = path56.join(targetDir, "SKILL.md");
|
|
27373
|
+
const content = await fs53.readFile(sourcePath, "utf-8");
|
|
26725
27374
|
const enrichedContent = injectSourceMetadata(content, source, sha);
|
|
26726
|
-
await
|
|
26727
|
-
await
|
|
27375
|
+
await fs53.mkdir(targetDir, { recursive: true });
|
|
27376
|
+
await fs53.writeFile(targetPath, enrichedContent, "utf-8");
|
|
26728
27377
|
return {
|
|
26729
27378
|
name,
|
|
26730
27379
|
filePath: targetPath,
|
|
@@ -26741,7 +27390,7 @@ async function installFromGitHub(source) {
|
|
|
26741
27390
|
);
|
|
26742
27391
|
return result;
|
|
26743
27392
|
}
|
|
26744
|
-
const tmpDir =
|
|
27393
|
+
const tmpDir = path56.join(os15.tmpdir(), `prjct-skill-${Date.now()}`);
|
|
26745
27394
|
try {
|
|
26746
27395
|
const cloneUrl = `https://github.com/${source.owner}/${source.repo}.git`;
|
|
26747
27396
|
await exec15(`git clone --depth 1 ${cloneUrl} ${tmpDir}`, { timeout: getTimeout("GIT_CLONE") });
|
|
@@ -26785,7 +27434,7 @@ async function installFromGitHub(source) {
|
|
|
26785
27434
|
}
|
|
26786
27435
|
} finally {
|
|
26787
27436
|
try {
|
|
26788
|
-
await
|
|
27437
|
+
await fs53.rm(tmpDir, { recursive: true, force: true });
|
|
26789
27438
|
} catch {
|
|
26790
27439
|
}
|
|
26791
27440
|
}
|
|
@@ -26795,14 +27444,14 @@ async function installFromLocal(source) {
|
|
|
26795
27444
|
const result = { installed: [], skipped: [], errors: [] };
|
|
26796
27445
|
const localPath = source.localPath;
|
|
26797
27446
|
try {
|
|
26798
|
-
await
|
|
27447
|
+
await fs53.access(localPath);
|
|
26799
27448
|
} catch {
|
|
26800
27449
|
result.errors.push(`Local path not found: ${localPath}`);
|
|
26801
27450
|
return result;
|
|
26802
27451
|
}
|
|
26803
|
-
const stat = await
|
|
27452
|
+
const stat = await fs53.stat(localPath);
|
|
26804
27453
|
if (stat.isFile()) {
|
|
26805
|
-
const name =
|
|
27454
|
+
const name = path56.basename(path56.dirname(localPath));
|
|
26806
27455
|
try {
|
|
26807
27456
|
const installed = await installSkillFile(localPath, name, source);
|
|
26808
27457
|
const lockEntry = {
|
|
@@ -26842,14 +27491,14 @@ async function installFromLocal(source) {
|
|
|
26842
27491
|
}
|
|
26843
27492
|
async function remove(name) {
|
|
26844
27493
|
const installDir = getInstallDir();
|
|
26845
|
-
const subdirPath =
|
|
27494
|
+
const subdirPath = path56.join(installDir, name);
|
|
26846
27495
|
try {
|
|
26847
|
-
await
|
|
27496
|
+
await fs53.rm(subdirPath, { recursive: true, force: true });
|
|
26848
27497
|
} catch {
|
|
26849
27498
|
}
|
|
26850
|
-
const flatPath =
|
|
27499
|
+
const flatPath = path56.join(installDir, `${name}.md`);
|
|
26851
27500
|
try {
|
|
26852
|
-
await
|
|
27501
|
+
await fs53.rm(flatPath, { force: true });
|
|
26853
27502
|
} catch {
|
|
26854
27503
|
}
|
|
26855
27504
|
return skillLock.removeEntry(name);
|
|
@@ -26897,8 +27546,8 @@ var init_skill_installer = __esm({
|
|
|
26897
27546
|
});
|
|
26898
27547
|
|
|
26899
27548
|
// core/services/stack-detector.ts
|
|
26900
|
-
import
|
|
26901
|
-
import
|
|
27549
|
+
import fs54 from "node:fs/promises";
|
|
27550
|
+
import path57 from "node:path";
|
|
26902
27551
|
var StackDetector;
|
|
26903
27552
|
var init_stack_detector = __esm({
|
|
26904
27553
|
"core/services/stack-detector.ts"() {
|
|
@@ -27057,8 +27706,8 @@ var init_stack_detector = __esm({
|
|
|
27057
27706
|
*/
|
|
27058
27707
|
async readPackageJson() {
|
|
27059
27708
|
try {
|
|
27060
|
-
const pkgPath =
|
|
27061
|
-
const content = await
|
|
27709
|
+
const pkgPath = path57.join(this.projectPath, "package.json");
|
|
27710
|
+
const content = await fs54.readFile(pkgPath, "utf-8");
|
|
27062
27711
|
return JSON.parse(content);
|
|
27063
27712
|
} catch {
|
|
27064
27713
|
return null;
|
|
@@ -27069,7 +27718,7 @@ var init_stack_detector = __esm({
|
|
|
27069
27718
|
*/
|
|
27070
27719
|
async fileExists(filename) {
|
|
27071
27720
|
try {
|
|
27072
|
-
await
|
|
27721
|
+
await fs54.access(path57.join(this.projectPath, filename));
|
|
27073
27722
|
return true;
|
|
27074
27723
|
} catch {
|
|
27075
27724
|
return false;
|
|
@@ -27081,8 +27730,8 @@ var init_stack_detector = __esm({
|
|
|
27081
27730
|
|
|
27082
27731
|
// core/services/sync-verifier.ts
|
|
27083
27732
|
import { exec as exec16 } from "node:child_process";
|
|
27084
|
-
import
|
|
27085
|
-
import
|
|
27733
|
+
import fs55 from "node:fs/promises";
|
|
27734
|
+
import path58 from "node:path";
|
|
27086
27735
|
import { promisify as promisify17 } from "node:util";
|
|
27087
27736
|
var execAsync10, BUILTIN_CHECKS, SyncVerifier, syncVerifier;
|
|
27088
27737
|
var init_sync_verifier = __esm({
|
|
@@ -27099,9 +27748,9 @@ var init_sync_verifier = __esm({
|
|
|
27099
27748
|
const expected = ["context/CLAUDE.md"];
|
|
27100
27749
|
const missing = [];
|
|
27101
27750
|
for (const file of expected) {
|
|
27102
|
-
const filePath =
|
|
27751
|
+
const filePath = path58.join(globalPath, file);
|
|
27103
27752
|
try {
|
|
27104
|
-
await
|
|
27753
|
+
await fs55.access(filePath);
|
|
27105
27754
|
} catch {
|
|
27106
27755
|
missing.push(file);
|
|
27107
27756
|
}
|
|
@@ -27122,9 +27771,9 @@ var init_sync_verifier = __esm({
|
|
|
27122
27771
|
const jsonFiles = ["storage/state.json"];
|
|
27123
27772
|
const invalid = [];
|
|
27124
27773
|
for (const file of jsonFiles) {
|
|
27125
|
-
const filePath =
|
|
27774
|
+
const filePath = path58.join(globalPath, file);
|
|
27126
27775
|
try {
|
|
27127
|
-
const content = await
|
|
27776
|
+
const content = await fs55.readFile(filePath, "utf-8");
|
|
27128
27777
|
JSON.parse(content);
|
|
27129
27778
|
} catch (error) {
|
|
27130
27779
|
if (!isNotFoundError(error)) {
|
|
@@ -27145,7 +27794,7 @@ var init_sync_verifier = __esm({
|
|
|
27145
27794
|
*/
|
|
27146
27795
|
async noSensitiveData(globalPath) {
|
|
27147
27796
|
const start = Date.now();
|
|
27148
|
-
const contextDir =
|
|
27797
|
+
const contextDir = path58.join(globalPath, "context");
|
|
27149
27798
|
const patterns = [
|
|
27150
27799
|
/(?:api[_-]?key|apikey)\s*[:=]\s*['"][^'"]{10,}/i,
|
|
27151
27800
|
/(?:password|passwd|pwd)\s*[:=]\s*['"][^'"]{4,}/i,
|
|
@@ -27153,10 +27802,10 @@ var init_sync_verifier = __esm({
|
|
|
27153
27802
|
];
|
|
27154
27803
|
const violations = [];
|
|
27155
27804
|
try {
|
|
27156
|
-
const files = await
|
|
27805
|
+
const files = await fs55.readdir(contextDir);
|
|
27157
27806
|
for (const file of files) {
|
|
27158
27807
|
if (!file.endsWith(".md")) continue;
|
|
27159
|
-
const content = await
|
|
27808
|
+
const content = await fs55.readFile(path58.join(contextDir, file), "utf-8");
|
|
27160
27809
|
for (const pattern of patterns) {
|
|
27161
27810
|
if (pattern.test(content)) {
|
|
27162
27811
|
violations.push(`${file}: potential sensitive data detected`);
|
|
@@ -27277,9 +27926,9 @@ var init_sync_verifier = __esm({
|
|
|
27277
27926
|
|
|
27278
27927
|
// core/services/sync-service.ts
|
|
27279
27928
|
import { exec as exec17 } from "node:child_process";
|
|
27280
|
-
import
|
|
27929
|
+
import fs56 from "node:fs/promises";
|
|
27281
27930
|
import os16 from "node:os";
|
|
27282
|
-
import
|
|
27931
|
+
import path59 from "node:path";
|
|
27283
27932
|
import { promisify as promisify18 } from "node:util";
|
|
27284
27933
|
var execAsync11, SyncService, syncService;
|
|
27285
27934
|
var init_sync_service = __esm({
|
|
@@ -27543,7 +28192,7 @@ var init_sync_service = __esm({
|
|
|
27543
28192
|
async ensureDirectories() {
|
|
27544
28193
|
const dirs = ["storage", "context", "agents", "memory", "analysis", "config", "sync"];
|
|
27545
28194
|
await Promise.all(
|
|
27546
|
-
dirs.map((dir) =>
|
|
28195
|
+
dirs.map((dir) => fs56.mkdir(path59.join(this.globalPath, dir), { recursive: true }))
|
|
27547
28196
|
);
|
|
27548
28197
|
}
|
|
27549
28198
|
// ==========================================================================
|
|
@@ -27614,7 +28263,7 @@ var init_sync_service = __esm({
|
|
|
27614
28263
|
const stats = {
|
|
27615
28264
|
fileCount: 0,
|
|
27616
28265
|
version: "0.0.0",
|
|
27617
|
-
name:
|
|
28266
|
+
name: path59.basename(this.projectPath),
|
|
27618
28267
|
ecosystem: "unknown",
|
|
27619
28268
|
projectType: "simple",
|
|
27620
28269
|
languages: [],
|
|
@@ -27631,8 +28280,8 @@ var init_sync_service = __esm({
|
|
|
27631
28280
|
stats.fileCount = 0;
|
|
27632
28281
|
}
|
|
27633
28282
|
try {
|
|
27634
|
-
const pkgPath =
|
|
27635
|
-
const pkg = JSON.parse(await
|
|
28283
|
+
const pkgPath = path59.join(this.projectPath, "package.json");
|
|
28284
|
+
const pkg = JSON.parse(await fs56.readFile(pkgPath, "utf-8"));
|
|
27636
28285
|
stats.version = pkg.version || "0.0.0";
|
|
27637
28286
|
stats.name = pkg.name || stats.name;
|
|
27638
28287
|
stats.ecosystem = "JavaScript";
|
|
@@ -27777,12 +28426,12 @@ var init_sync_service = __esm({
|
|
|
27777
28426
|
// ==========================================================================
|
|
27778
28427
|
async generateAgents(stack, stats) {
|
|
27779
28428
|
const agents = [];
|
|
27780
|
-
const agentsPath =
|
|
28429
|
+
const agentsPath = path59.join(this.globalPath, "agents");
|
|
27781
28430
|
try {
|
|
27782
|
-
const files = await
|
|
28431
|
+
const files = await fs56.readdir(agentsPath);
|
|
27783
28432
|
for (const file of files) {
|
|
27784
28433
|
if (file.endsWith(".md")) {
|
|
27785
|
-
await
|
|
28434
|
+
await fs56.unlink(path59.join(agentsPath, file));
|
|
27786
28435
|
}
|
|
27787
28436
|
}
|
|
27788
28437
|
} catch (error) {
|
|
@@ -27825,10 +28474,10 @@ var init_sync_service = __esm({
|
|
|
27825
28474
|
* Reads the agents directory and returns metadata without regenerating files.
|
|
27826
28475
|
*/
|
|
27827
28476
|
async loadExistingAgents() {
|
|
27828
|
-
const agentsPath =
|
|
28477
|
+
const agentsPath = path59.join(this.globalPath, "agents");
|
|
27829
28478
|
const agents = [];
|
|
27830
28479
|
try {
|
|
27831
|
-
const files = await
|
|
28480
|
+
const files = await fs56.readdir(agentsPath);
|
|
27832
28481
|
const workflowNames = /* @__PURE__ */ new Set(["prjct-workflow", "prjct-planner", "prjct-shipper"]);
|
|
27833
28482
|
for (const file of files) {
|
|
27834
28483
|
if (!file.endsWith(".md")) continue;
|
|
@@ -27852,7 +28501,7 @@ var init_sync_service = __esm({
|
|
|
27852
28501
|
let resolved = content;
|
|
27853
28502
|
for (const match of matches) {
|
|
27854
28503
|
const partialName = match[1];
|
|
27855
|
-
const partialPath =
|
|
28504
|
+
const partialPath = path59.join(
|
|
27856
28505
|
__dirname,
|
|
27857
28506
|
"..",
|
|
27858
28507
|
"..",
|
|
@@ -27861,7 +28510,7 @@ var init_sync_service = __esm({
|
|
|
27861
28510
|
`${partialName}.md`
|
|
27862
28511
|
);
|
|
27863
28512
|
try {
|
|
27864
|
-
const partialContent = await
|
|
28513
|
+
const partialContent = await fs56.readFile(partialPath, "utf-8");
|
|
27865
28514
|
resolved = resolved.replace(match[0], partialContent.trim());
|
|
27866
28515
|
} catch {
|
|
27867
28516
|
resolved = resolved.replace(match[0], `<!-- partial "${partialName}" not found -->`);
|
|
@@ -27872,7 +28521,7 @@ var init_sync_service = __esm({
|
|
|
27872
28521
|
async generateWorkflowAgent(name, agentsPath) {
|
|
27873
28522
|
let content = "";
|
|
27874
28523
|
try {
|
|
27875
|
-
const templatePath =
|
|
28524
|
+
const templatePath = path59.join(
|
|
27876
28525
|
__dirname,
|
|
27877
28526
|
"..",
|
|
27878
28527
|
"..",
|
|
@@ -27881,7 +28530,7 @@ var init_sync_service = __esm({
|
|
|
27881
28530
|
"workflow",
|
|
27882
28531
|
`${name}.md`
|
|
27883
28532
|
);
|
|
27884
|
-
content = await
|
|
28533
|
+
content = await fs56.readFile(templatePath, "utf-8");
|
|
27885
28534
|
content = await this.resolveTemplateIncludes(content);
|
|
27886
28535
|
} catch (error) {
|
|
27887
28536
|
logger_default.debug("Workflow agent template not found, generating minimal", {
|
|
@@ -27890,12 +28539,12 @@ var init_sync_service = __esm({
|
|
|
27890
28539
|
});
|
|
27891
28540
|
content = this.generateMinimalWorkflowAgent(name);
|
|
27892
28541
|
}
|
|
27893
|
-
await
|
|
28542
|
+
await fs56.writeFile(path59.join(agentsPath, `${name}.md`), content, "utf-8");
|
|
27894
28543
|
}
|
|
27895
28544
|
async generateDomainAgent(name, agentsPath, stats, stack) {
|
|
27896
28545
|
let content = "";
|
|
27897
28546
|
try {
|
|
27898
|
-
const templatePath =
|
|
28547
|
+
const templatePath = path59.join(
|
|
27899
28548
|
__dirname,
|
|
27900
28549
|
"..",
|
|
27901
28550
|
"..",
|
|
@@ -27904,7 +28553,7 @@ var init_sync_service = __esm({
|
|
|
27904
28553
|
"domain",
|
|
27905
28554
|
`${name}.md`
|
|
27906
28555
|
);
|
|
27907
|
-
content = await
|
|
28556
|
+
content = await fs56.readFile(templatePath, "utf-8");
|
|
27908
28557
|
content = await this.resolveTemplateIncludes(content);
|
|
27909
28558
|
content = content.replace("{projectName}", stats.name);
|
|
27910
28559
|
content = content.replace("{frameworks}", stack.frameworks.join(", ") || "None detected");
|
|
@@ -27916,7 +28565,7 @@ var init_sync_service = __esm({
|
|
|
27916
28565
|
});
|
|
27917
28566
|
content = this.generateMinimalDomainAgent(name, stats, stack);
|
|
27918
28567
|
}
|
|
27919
|
-
await
|
|
28568
|
+
await fs56.writeFile(path59.join(agentsPath, `${name}.md`), content, "utf-8");
|
|
27920
28569
|
}
|
|
27921
28570
|
generateMinimalWorkflowAgent(name) {
|
|
27922
28571
|
const descriptions = {
|
|
@@ -27984,8 +28633,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
27984
28633
|
})),
|
|
27985
28634
|
agentSkillMap: Object.fromEntries(skills.map((s) => [s.agent, s.skill]))
|
|
27986
28635
|
};
|
|
27987
|
-
|
|
27988
|
-
|
|
28636
|
+
fs56.writeFile(
|
|
28637
|
+
path59.join(this.globalPath, "config", "skills.json"),
|
|
27989
28638
|
JSON.stringify(skillsConfig, null, 2),
|
|
27990
28639
|
"utf-8"
|
|
27991
28640
|
).catch((error) => {
|
|
@@ -28003,7 +28652,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28003
28652
|
async autoInstallSkills(agents) {
|
|
28004
28653
|
const results = [];
|
|
28005
28654
|
try {
|
|
28006
|
-
const mappingsPath =
|
|
28655
|
+
const mappingsPath = path59.join(
|
|
28007
28656
|
__dirname,
|
|
28008
28657
|
"..",
|
|
28009
28658
|
"..",
|
|
@@ -28011,7 +28660,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28011
28660
|
"config",
|
|
28012
28661
|
"skill-mappings.json"
|
|
28013
28662
|
);
|
|
28014
|
-
const mappingsContent = await
|
|
28663
|
+
const mappingsContent = await fs56.readFile(mappingsPath, "utf-8");
|
|
28015
28664
|
const mappings = JSON.parse(mappingsContent);
|
|
28016
28665
|
const agentToSkillMap = mappings.agentToSkillMap || {};
|
|
28017
28666
|
const packagesToInstall = [];
|
|
@@ -28024,18 +28673,18 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28024
28673
|
}
|
|
28025
28674
|
}
|
|
28026
28675
|
if (packagesToInstall.length === 0) return results;
|
|
28027
|
-
const skillsDir =
|
|
28676
|
+
const skillsDir = path59.join(os16.homedir(), ".claude", "skills");
|
|
28028
28677
|
for (const { pkg, agent } of packagesToInstall) {
|
|
28029
28678
|
const skillName = pkg.split("/").pop() || pkg;
|
|
28030
|
-
const subdirPath =
|
|
28031
|
-
const flatPath =
|
|
28679
|
+
const subdirPath = path59.join(skillsDir, skillName, "SKILL.md");
|
|
28680
|
+
const flatPath = path59.join(skillsDir, `${skillName}.md`);
|
|
28032
28681
|
let alreadyInstalled = false;
|
|
28033
28682
|
try {
|
|
28034
|
-
await
|
|
28683
|
+
await fs56.access(subdirPath);
|
|
28035
28684
|
alreadyInstalled = true;
|
|
28036
28685
|
} catch {
|
|
28037
28686
|
try {
|
|
28038
|
-
await
|
|
28687
|
+
await fs56.access(flatPath);
|
|
28039
28688
|
alreadyInstalled = true;
|
|
28040
28689
|
} catch {
|
|
28041
28690
|
}
|
|
@@ -28087,10 +28736,10 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28087
28736
|
// PROJECT.JSON UPDATE
|
|
28088
28737
|
// ==========================================================================
|
|
28089
28738
|
async updateProjectJson(git, stats) {
|
|
28090
|
-
const projectJsonPath =
|
|
28739
|
+
const projectJsonPath = path59.join(this.globalPath, "project.json");
|
|
28091
28740
|
let existing = {};
|
|
28092
28741
|
try {
|
|
28093
|
-
existing = JSON.parse(await
|
|
28742
|
+
existing = JSON.parse(await fs56.readFile(projectJsonPath, "utf-8"));
|
|
28094
28743
|
} catch (error) {
|
|
28095
28744
|
logger_default.debug("No existing project.json", {
|
|
28096
28745
|
path: projectJsonPath,
|
|
@@ -28116,16 +28765,16 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28116
28765
|
lastSyncCommit: git.recentCommits[0]?.hash || null,
|
|
28117
28766
|
lastSyncBranch: git.branch
|
|
28118
28767
|
};
|
|
28119
|
-
await
|
|
28768
|
+
await fs56.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
28120
28769
|
}
|
|
28121
28770
|
// ==========================================================================
|
|
28122
28771
|
// STATE.JSON UPDATE
|
|
28123
28772
|
// ==========================================================================
|
|
28124
28773
|
async updateStateJson(stats, stack) {
|
|
28125
|
-
const statePath =
|
|
28774
|
+
const statePath = path59.join(this.globalPath, "storage", "state.json");
|
|
28126
28775
|
let state = {};
|
|
28127
28776
|
try {
|
|
28128
|
-
state = JSON.parse(await
|
|
28777
|
+
state = JSON.parse(await fs56.readFile(statePath, "utf-8"));
|
|
28129
28778
|
} catch (error) {
|
|
28130
28779
|
logger_default.debug("No existing state.json", { path: statePath, error: getErrorMessage(error) });
|
|
28131
28780
|
}
|
|
@@ -28153,7 +28802,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28153
28802
|
lastAction: "Synced project",
|
|
28154
28803
|
nextAction: 'Run `p. task "description"` to start working'
|
|
28155
28804
|
};
|
|
28156
|
-
await
|
|
28805
|
+
await fs56.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
|
|
28157
28806
|
try {
|
|
28158
28807
|
await localStateGenerator.generate(
|
|
28159
28808
|
this.projectPath,
|
|
@@ -28167,7 +28816,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28167
28816
|
// MEMORY LOGGING
|
|
28168
28817
|
// ==========================================================================
|
|
28169
28818
|
async logToMemory(git, stats) {
|
|
28170
|
-
const memoryPath =
|
|
28819
|
+
const memoryPath = path59.join(this.globalPath, "memory", "events.jsonl");
|
|
28171
28820
|
const event = {
|
|
28172
28821
|
ts: getTimestamp(),
|
|
28173
28822
|
action: "sync",
|
|
@@ -28176,7 +28825,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28176
28825
|
fileCount: stats.fileCount,
|
|
28177
28826
|
commitCount: git.commits
|
|
28178
28827
|
};
|
|
28179
|
-
await
|
|
28828
|
+
await fs56.appendFile(memoryPath, `${JSON.stringify(event)}
|
|
28180
28829
|
`, "utf-8");
|
|
28181
28830
|
}
|
|
28182
28831
|
// ==========================================================================
|
|
@@ -28196,8 +28845,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28196
28845
|
let filteredChars = 0;
|
|
28197
28846
|
for (const file of contextFiles) {
|
|
28198
28847
|
try {
|
|
28199
|
-
const filePath =
|
|
28200
|
-
const content = await
|
|
28848
|
+
const filePath = path59.join(this.globalPath, file);
|
|
28849
|
+
const content = await fs56.readFile(filePath, "utf-8");
|
|
28201
28850
|
filteredChars += content.length;
|
|
28202
28851
|
} catch (error) {
|
|
28203
28852
|
logger_default.debug("Context file not found for metrics", { file, error: getErrorMessage(error) });
|
|
@@ -28205,8 +28854,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28205
28854
|
}
|
|
28206
28855
|
for (const agent of agents) {
|
|
28207
28856
|
try {
|
|
28208
|
-
const agentPath =
|
|
28209
|
-
const content = await
|
|
28857
|
+
const agentPath = path59.join(this.globalPath, "agents", `${agent.name}.md`);
|
|
28858
|
+
const content = await fs56.readFile(agentPath, "utf-8");
|
|
28210
28859
|
filteredChars += content.length;
|
|
28211
28860
|
} catch (error) {
|
|
28212
28861
|
logger_default.debug("Agent file not found for metrics", {
|
|
@@ -28302,7 +28951,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28302
28951
|
// ==========================================================================
|
|
28303
28952
|
async fileExists(filename) {
|
|
28304
28953
|
try {
|
|
28305
|
-
await
|
|
28954
|
+
await fs56.access(path59.join(this.projectPath, filename));
|
|
28306
28955
|
return true;
|
|
28307
28956
|
} catch (error) {
|
|
28308
28957
|
logger_default.debug("File not found", { filename, error: getErrorMessage(error) });
|
|
@@ -28311,8 +28960,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
28311
28960
|
}
|
|
28312
28961
|
async getCliVersion() {
|
|
28313
28962
|
try {
|
|
28314
|
-
const pkgPath =
|
|
28315
|
-
const pkg = JSON.parse(await
|
|
28963
|
+
const pkgPath = path59.join(__dirname, "..", "..", "package.json");
|
|
28964
|
+
const pkg = JSON.parse(await fs56.readFile(pkgPath, "utf-8"));
|
|
28316
28965
|
return pkg.version || "0.0.0";
|
|
28317
28966
|
} catch (error) {
|
|
28318
28967
|
logger_default.debug("Failed to read CLI version", { error: getErrorMessage(error) });
|
|
@@ -28473,22 +29122,22 @@ __export(uninstall_exports, {
|
|
|
28473
29122
|
uninstall: () => uninstall
|
|
28474
29123
|
});
|
|
28475
29124
|
import { execSync as execSync3 } from "node:child_process";
|
|
28476
|
-
import
|
|
29125
|
+
import fs57 from "node:fs/promises";
|
|
28477
29126
|
import os17 from "node:os";
|
|
28478
|
-
import
|
|
29127
|
+
import path60 from "node:path";
|
|
28479
29128
|
import readline2 from "node:readline";
|
|
28480
29129
|
import chalk12 from "chalk";
|
|
28481
29130
|
async function getDirectorySize(dirPath) {
|
|
28482
29131
|
let totalSize = 0;
|
|
28483
29132
|
try {
|
|
28484
|
-
const entries = await
|
|
29133
|
+
const entries = await fs57.readdir(dirPath, { withFileTypes: true });
|
|
28485
29134
|
for (const entry of entries) {
|
|
28486
|
-
const entryPath =
|
|
29135
|
+
const entryPath = path60.join(dirPath, entry.name);
|
|
28487
29136
|
if (entry.isDirectory()) {
|
|
28488
29137
|
totalSize += await getDirectorySize(entryPath);
|
|
28489
29138
|
} else {
|
|
28490
29139
|
try {
|
|
28491
|
-
const stats = await
|
|
29140
|
+
const stats = await fs57.stat(entryPath);
|
|
28492
29141
|
totalSize += stats.size;
|
|
28493
29142
|
} catch {
|
|
28494
29143
|
}
|
|
@@ -28507,7 +29156,7 @@ function formatSize(bytes) {
|
|
|
28507
29156
|
}
|
|
28508
29157
|
async function countDirectoryItems(dirPath) {
|
|
28509
29158
|
try {
|
|
28510
|
-
const entries = await
|
|
29159
|
+
const entries = await fs57.readdir(dirPath, { withFileTypes: true });
|
|
28511
29160
|
return entries.filter((e) => e.isDirectory()).length;
|
|
28512
29161
|
} catch {
|
|
28513
29162
|
return 0;
|
|
@@ -28540,7 +29189,7 @@ async function gatherUninstallItems() {
|
|
|
28540
29189
|
const providerPaths = getProviderPaths();
|
|
28541
29190
|
const prjctCliPath = path_manager_default.getGlobalBasePath();
|
|
28542
29191
|
const prjctCliExists = await fileExists(prjctCliPath);
|
|
28543
|
-
const projectCount = prjctCliExists ? await countDirectoryItems(
|
|
29192
|
+
const projectCount = prjctCliExists ? await countDirectoryItems(path60.join(prjctCliPath, "projects")) : 0;
|
|
28544
29193
|
const prjctCliSize = prjctCliExists ? await getDirectorySize(prjctCliPath) : 0;
|
|
28545
29194
|
items.push({
|
|
28546
29195
|
path: prjctCliPath,
|
|
@@ -28550,12 +29199,12 @@ async function gatherUninstallItems() {
|
|
|
28550
29199
|
count: projectCount,
|
|
28551
29200
|
exists: prjctCliExists
|
|
28552
29201
|
});
|
|
28553
|
-
const claudeMdPath =
|
|
29202
|
+
const claudeMdPath = path60.join(providerPaths.claude.config, "CLAUDE.md");
|
|
28554
29203
|
const claudeMdExists = await fileExists(claudeMdPath);
|
|
28555
29204
|
let hasPrjctSection = false;
|
|
28556
29205
|
if (claudeMdExists) {
|
|
28557
29206
|
try {
|
|
28558
|
-
const content = await
|
|
29207
|
+
const content = await fs57.readFile(claudeMdPath, "utf-8");
|
|
28559
29208
|
hasPrjctSection = content.includes(PRJCT_START_MARKER) && content.includes(PRJCT_END_MARKER);
|
|
28560
29209
|
} catch {
|
|
28561
29210
|
}
|
|
@@ -28584,7 +29233,7 @@ async function gatherUninstallItems() {
|
|
|
28584
29233
|
description: "Claude router",
|
|
28585
29234
|
exists: claudeRouterExists
|
|
28586
29235
|
});
|
|
28587
|
-
const statusLinePath =
|
|
29236
|
+
const statusLinePath = path60.join(providerPaths.claude.config, "prjct-statusline.sh");
|
|
28588
29237
|
const statusLineExists = await fileExists(statusLinePath);
|
|
28589
29238
|
items.push({
|
|
28590
29239
|
path: statusLinePath,
|
|
@@ -28600,12 +29249,12 @@ async function gatherUninstallItems() {
|
|
|
28600
29249
|
description: "Gemini router",
|
|
28601
29250
|
exists: geminiRouterExists
|
|
28602
29251
|
});
|
|
28603
|
-
const geminiMdPath =
|
|
29252
|
+
const geminiMdPath = path60.join(providerPaths.gemini.config, "GEMINI.md");
|
|
28604
29253
|
const geminiMdExists = await fileExists(geminiMdPath);
|
|
28605
29254
|
let hasGeminiPrjctSection = false;
|
|
28606
29255
|
if (geminiMdExists) {
|
|
28607
29256
|
try {
|
|
28608
|
-
const content = await
|
|
29257
|
+
const content = await fs57.readFile(geminiMdPath, "utf-8");
|
|
28609
29258
|
hasGeminiPrjctSection = content.includes(PRJCT_START_MARKER) && content.includes(PRJCT_END_MARKER);
|
|
28610
29259
|
} catch {
|
|
28611
29260
|
}
|
|
@@ -28622,7 +29271,7 @@ async function gatherUninstallItems() {
|
|
|
28622
29271
|
}
|
|
28623
29272
|
async function removePrjctSection(filePath) {
|
|
28624
29273
|
try {
|
|
28625
|
-
const content = await
|
|
29274
|
+
const content = await fs57.readFile(filePath, "utf-8");
|
|
28626
29275
|
if (!content.includes(PRJCT_START_MARKER) || !content.includes(PRJCT_END_MARKER)) {
|
|
28627
29276
|
return false;
|
|
28628
29277
|
}
|
|
@@ -28631,9 +29280,9 @@ async function removePrjctSection(filePath) {
|
|
|
28631
29280
|
let newContent = content.substring(0, startIndex) + content.substring(endIndex);
|
|
28632
29281
|
newContent = newContent.replace(/\n{3,}/g, "\n\n").trim();
|
|
28633
29282
|
if (!newContent || newContent.trim().length === 0) {
|
|
28634
|
-
await
|
|
29283
|
+
await fs57.unlink(filePath);
|
|
28635
29284
|
} else {
|
|
28636
|
-
await
|
|
29285
|
+
await fs57.writeFile(filePath, `${newContent}
|
|
28637
29286
|
`, "utf-8");
|
|
28638
29287
|
}
|
|
28639
29288
|
return true;
|
|
@@ -28644,12 +29293,12 @@ async function removePrjctSection(filePath) {
|
|
|
28644
29293
|
async function createBackup3() {
|
|
28645
29294
|
const homeDir = os17.homedir();
|
|
28646
29295
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
|
|
28647
|
-
const backupDir =
|
|
29296
|
+
const backupDir = path60.join(homeDir, `.prjct-backup-${timestamp}`);
|
|
28648
29297
|
try {
|
|
28649
|
-
await
|
|
29298
|
+
await fs57.mkdir(backupDir, { recursive: true });
|
|
28650
29299
|
const prjctCliPath = path_manager_default.getGlobalBasePath();
|
|
28651
29300
|
if (await fileExists(prjctCliPath)) {
|
|
28652
|
-
await copyDirectory(prjctCliPath,
|
|
29301
|
+
await copyDirectory(prjctCliPath, path60.join(backupDir, ".prjct-cli"));
|
|
28653
29302
|
}
|
|
28654
29303
|
return backupDir;
|
|
28655
29304
|
} catch {
|
|
@@ -28657,15 +29306,15 @@ async function createBackup3() {
|
|
|
28657
29306
|
}
|
|
28658
29307
|
}
|
|
28659
29308
|
async function copyDirectory(src, dest) {
|
|
28660
|
-
await
|
|
28661
|
-
const entries = await
|
|
29309
|
+
await fs57.mkdir(dest, { recursive: true });
|
|
29310
|
+
const entries = await fs57.readdir(src, { withFileTypes: true });
|
|
28662
29311
|
for (const entry of entries) {
|
|
28663
|
-
const srcPath =
|
|
28664
|
-
const destPath =
|
|
29312
|
+
const srcPath = path60.join(src, entry.name);
|
|
29313
|
+
const destPath = path60.join(dest, entry.name);
|
|
28665
29314
|
if (entry.isDirectory()) {
|
|
28666
29315
|
await copyDirectory(srcPath, destPath);
|
|
28667
29316
|
} else {
|
|
28668
|
-
await
|
|
29317
|
+
await fs57.copyFile(srcPath, destPath);
|
|
28669
29318
|
}
|
|
28670
29319
|
}
|
|
28671
29320
|
}
|
|
@@ -28681,10 +29330,10 @@ async function performUninstall(items, installation, options) {
|
|
|
28681
29330
|
deleted.push(item.path);
|
|
28682
29331
|
}
|
|
28683
29332
|
} else if (item.type === "directory") {
|
|
28684
|
-
await
|
|
29333
|
+
await fs57.rm(item.path, { recursive: true, force: true });
|
|
28685
29334
|
deleted.push(item.path);
|
|
28686
29335
|
} else if (item.type === "file") {
|
|
28687
|
-
await
|
|
29336
|
+
await fs57.unlink(item.path);
|
|
28688
29337
|
deleted.push(item.path);
|
|
28689
29338
|
}
|
|
28690
29339
|
} catch (error) {
|
|
@@ -28861,7 +29510,7 @@ __export(watch_service_exports, {
|
|
|
28861
29510
|
WatchService: () => WatchService,
|
|
28862
29511
|
watchService: () => watchService
|
|
28863
29512
|
});
|
|
28864
|
-
import
|
|
29513
|
+
import path61 from "node:path";
|
|
28865
29514
|
import chalk13 from "chalk";
|
|
28866
29515
|
import chokidar from "chokidar";
|
|
28867
29516
|
var TRIGGER_PATTERNS, IGNORE_PATTERNS2, WatchService, watchService;
|
|
@@ -29082,7 +29731,7 @@ ${chalk13.dim(`[${timestamp}]`)} ${chalk13.cyan("\u27F3")} ${filesSummary} chang
|
|
|
29082
29731
|
printStartup() {
|
|
29083
29732
|
console.log("");
|
|
29084
29733
|
console.log(chalk13.cyan("\u{1F441}\uFE0F Watching for changes..."));
|
|
29085
|
-
console.log(chalk13.dim(` Project: ${
|
|
29734
|
+
console.log(chalk13.dim(` Project: ${path61.basename(this.projectPath)}`));
|
|
29086
29735
|
console.log(chalk13.dim(` Debounce: ${this.options.debounceMs}ms`));
|
|
29087
29736
|
console.log(chalk13.dim(` Min interval: ${this.options.minIntervalMs / 1e3}s`));
|
|
29088
29737
|
console.log("");
|
|
@@ -29815,9 +30464,9 @@ __export(setup_exports, {
|
|
|
29815
30464
|
run: () => run
|
|
29816
30465
|
});
|
|
29817
30466
|
import { execSync as execSync4 } from "node:child_process";
|
|
29818
|
-
import
|
|
30467
|
+
import fs58 from "node:fs/promises";
|
|
29819
30468
|
import os18 from "node:os";
|
|
29820
|
-
import
|
|
30469
|
+
import path62 from "node:path";
|
|
29821
30470
|
import chalk15 from "chalk";
|
|
29822
30471
|
async function installAICLI(provider) {
|
|
29823
30472
|
const packageName = provider.name === "claude" ? "@anthropic-ai/claude-code" : "@google/gemini-cli";
|
|
@@ -29956,12 +30605,12 @@ async function run() {
|
|
|
29956
30605
|
}
|
|
29957
30606
|
async function installGeminiRouter() {
|
|
29958
30607
|
try {
|
|
29959
|
-
const geminiCommandsDir =
|
|
29960
|
-
const routerSource =
|
|
29961
|
-
const routerDest =
|
|
29962
|
-
await
|
|
30608
|
+
const geminiCommandsDir = path62.join(os18.homedir(), ".gemini", "commands");
|
|
30609
|
+
const routerSource = path62.join(PACKAGE_ROOT, "templates", "commands", "p.toml");
|
|
30610
|
+
const routerDest = path62.join(geminiCommandsDir, "p.toml");
|
|
30611
|
+
await fs58.mkdir(geminiCommandsDir, { recursive: true });
|
|
29963
30612
|
if (await fileExists(routerSource)) {
|
|
29964
|
-
await
|
|
30613
|
+
await fs58.copyFile(routerSource, routerDest);
|
|
29965
30614
|
return true;
|
|
29966
30615
|
}
|
|
29967
30616
|
return false;
|
|
@@ -29972,15 +30621,15 @@ async function installGeminiRouter() {
|
|
|
29972
30621
|
}
|
|
29973
30622
|
async function installGeminiGlobalConfig() {
|
|
29974
30623
|
try {
|
|
29975
|
-
const geminiDir =
|
|
29976
|
-
const globalConfigPath =
|
|
29977
|
-
const templatePath =
|
|
29978
|
-
await
|
|
29979
|
-
const templateContent = await
|
|
30624
|
+
const geminiDir = path62.join(os18.homedir(), ".gemini");
|
|
30625
|
+
const globalConfigPath = path62.join(geminiDir, "GEMINI.md");
|
|
30626
|
+
const templatePath = path62.join(PACKAGE_ROOT, "templates", "global", "GEMINI.md");
|
|
30627
|
+
await fs58.mkdir(geminiDir, { recursive: true });
|
|
30628
|
+
const templateContent = await fs58.readFile(templatePath, "utf-8");
|
|
29980
30629
|
let existingContent = "";
|
|
29981
30630
|
let configExists = false;
|
|
29982
30631
|
try {
|
|
29983
|
-
existingContent = await
|
|
30632
|
+
existingContent = await fs58.readFile(globalConfigPath, "utf-8");
|
|
29984
30633
|
configExists = true;
|
|
29985
30634
|
} catch (error) {
|
|
29986
30635
|
if (isNotFoundError(error)) {
|
|
@@ -29990,7 +30639,7 @@ async function installGeminiGlobalConfig() {
|
|
|
29990
30639
|
}
|
|
29991
30640
|
}
|
|
29992
30641
|
if (!configExists) {
|
|
29993
|
-
await
|
|
30642
|
+
await fs58.writeFile(globalConfigPath, templateContent, "utf-8");
|
|
29994
30643
|
return { success: true, action: "created" };
|
|
29995
30644
|
}
|
|
29996
30645
|
const startMarker = "<!-- prjct:start - DO NOT REMOVE THIS MARKER -->";
|
|
@@ -30000,7 +30649,7 @@ async function installGeminiGlobalConfig() {
|
|
|
30000
30649
|
const updatedContent2 = `${existingContent}
|
|
30001
30650
|
|
|
30002
30651
|
${templateContent}`;
|
|
30003
|
-
await
|
|
30652
|
+
await fs58.writeFile(globalConfigPath, updatedContent2, "utf-8");
|
|
30004
30653
|
return { success: true, action: "appended" };
|
|
30005
30654
|
}
|
|
30006
30655
|
const beforeMarker = existingContent.substring(0, existingContent.indexOf(startMarker));
|
|
@@ -30012,7 +30661,7 @@ ${templateContent}`;
|
|
|
30012
30661
|
templateContent.indexOf(endMarker) + endMarker.length
|
|
30013
30662
|
);
|
|
30014
30663
|
const updatedContent = beforeMarker + prjctSection + afterMarker;
|
|
30015
|
-
await
|
|
30664
|
+
await fs58.writeFile(globalConfigPath, updatedContent, "utf-8");
|
|
30016
30665
|
return { success: true, action: "updated" };
|
|
30017
30666
|
} catch (error) {
|
|
30018
30667
|
logger_default.warn(`Gemini config warning: ${getErrorMessage2(error)}`);
|
|
@@ -30021,18 +30670,18 @@ ${templateContent}`;
|
|
|
30021
30670
|
}
|
|
30022
30671
|
async function installAntigravitySkill() {
|
|
30023
30672
|
try {
|
|
30024
|
-
const antigravitySkillsDir =
|
|
30025
|
-
const prjctSkillDir =
|
|
30026
|
-
const skillMdPath =
|
|
30027
|
-
const templatePath =
|
|
30028
|
-
await
|
|
30673
|
+
const antigravitySkillsDir = path62.join(os18.homedir(), ".gemini", "antigravity", "skills");
|
|
30674
|
+
const prjctSkillDir = path62.join(antigravitySkillsDir, "prjct");
|
|
30675
|
+
const skillMdPath = path62.join(prjctSkillDir, "SKILL.md");
|
|
30676
|
+
const templatePath = path62.join(PACKAGE_ROOT, "templates", "antigravity", "SKILL.md");
|
|
30677
|
+
await fs58.mkdir(prjctSkillDir, { recursive: true });
|
|
30029
30678
|
const skillExists = await fileExists(skillMdPath);
|
|
30030
30679
|
if (!await fileExists(templatePath)) {
|
|
30031
30680
|
logger_default.warn("Antigravity SKILL.md template not found");
|
|
30032
30681
|
return { success: false, action: null };
|
|
30033
30682
|
}
|
|
30034
|
-
const templateContent = await
|
|
30035
|
-
await
|
|
30683
|
+
const templateContent = await fs58.readFile(templatePath, "utf-8");
|
|
30684
|
+
await fs58.writeFile(skillMdPath, templateContent, "utf-8");
|
|
30036
30685
|
return { success: true, action: skillExists ? "updated" : "created" };
|
|
30037
30686
|
} catch (error) {
|
|
30038
30687
|
logger_default.warn(`Antigravity skill warning: ${getErrorMessage2(error)}`);
|
|
@@ -30051,24 +30700,24 @@ async function installCursorProject(projectRoot) {
|
|
|
30051
30700
|
gitignoreUpdated: false
|
|
30052
30701
|
};
|
|
30053
30702
|
try {
|
|
30054
|
-
const cursorDir =
|
|
30055
|
-
const rulesDir =
|
|
30056
|
-
const commandsDir =
|
|
30057
|
-
const routerMdcDest =
|
|
30058
|
-
const routerMdcSource =
|
|
30059
|
-
const cursorCommandsSource =
|
|
30060
|
-
await
|
|
30061
|
-
await
|
|
30703
|
+
const cursorDir = path62.join(projectRoot, ".cursor");
|
|
30704
|
+
const rulesDir = path62.join(cursorDir, "rules");
|
|
30705
|
+
const commandsDir = path62.join(cursorDir, "commands");
|
|
30706
|
+
const routerMdcDest = path62.join(rulesDir, "prjct.mdc");
|
|
30707
|
+
const routerMdcSource = path62.join(PACKAGE_ROOT, "templates", "cursor", "router.mdc");
|
|
30708
|
+
const cursorCommandsSource = path62.join(PACKAGE_ROOT, "templates", "cursor", "commands");
|
|
30709
|
+
await fs58.mkdir(rulesDir, { recursive: true });
|
|
30710
|
+
await fs58.mkdir(commandsDir, { recursive: true });
|
|
30062
30711
|
if (await fileExists(routerMdcSource)) {
|
|
30063
|
-
await
|
|
30712
|
+
await fs58.copyFile(routerMdcSource, routerMdcDest);
|
|
30064
30713
|
result.rulesCreated = true;
|
|
30065
30714
|
}
|
|
30066
30715
|
if (await fileExists(cursorCommandsSource)) {
|
|
30067
|
-
const commandFiles = (await
|
|
30716
|
+
const commandFiles = (await fs58.readdir(cursorCommandsSource)).filter((f) => f.endsWith(".md"));
|
|
30068
30717
|
for (const file of commandFiles) {
|
|
30069
|
-
const src =
|
|
30070
|
-
const dest =
|
|
30071
|
-
await
|
|
30718
|
+
const src = path62.join(cursorCommandsSource, file);
|
|
30719
|
+
const dest = path62.join(commandsDir, file);
|
|
30720
|
+
await fs58.copyFile(src, dest);
|
|
30072
30721
|
}
|
|
30073
30722
|
result.commandsCreated = commandFiles.length > 0;
|
|
30074
30723
|
}
|
|
@@ -30082,7 +30731,7 @@ async function installCursorProject(projectRoot) {
|
|
|
30082
30731
|
}
|
|
30083
30732
|
async function addCursorToGitignore(projectRoot) {
|
|
30084
30733
|
try {
|
|
30085
|
-
const gitignorePath =
|
|
30734
|
+
const gitignorePath = path62.join(projectRoot, ".gitignore");
|
|
30086
30735
|
const entriesToAdd = [
|
|
30087
30736
|
"# prjct Cursor routers (regenerated per-developer)",
|
|
30088
30737
|
".cursor/rules/prjct.mdc",
|
|
@@ -30097,7 +30746,7 @@ async function addCursorToGitignore(projectRoot) {
|
|
|
30097
30746
|
let content = "";
|
|
30098
30747
|
let configExists = false;
|
|
30099
30748
|
try {
|
|
30100
|
-
content = await
|
|
30749
|
+
content = await fs58.readFile(gitignorePath, "utf-8");
|
|
30101
30750
|
configExists = true;
|
|
30102
30751
|
} catch (error) {
|
|
30103
30752
|
if (!isNotFoundError(error)) {
|
|
@@ -30112,7 +30761,7 @@ async function addCursorToGitignore(projectRoot) {
|
|
|
30112
30761
|
${entriesToAdd.join("\n")}
|
|
30113
30762
|
` : `${entriesToAdd.join("\n")}
|
|
30114
30763
|
`;
|
|
30115
|
-
await
|
|
30764
|
+
await fs58.writeFile(gitignorePath, newContent, "utf-8");
|
|
30116
30765
|
return true;
|
|
30117
30766
|
} catch (error) {
|
|
30118
30767
|
logger_default.warn(`Gitignore update warning: ${getErrorMessage2(error)}`);
|
|
@@ -30120,11 +30769,11 @@ ${entriesToAdd.join("\n")}
|
|
|
30120
30769
|
}
|
|
30121
30770
|
}
|
|
30122
30771
|
async function hasCursorProject(projectRoot) {
|
|
30123
|
-
return await fileExists(
|
|
30772
|
+
return await fileExists(path62.join(projectRoot, ".cursor"));
|
|
30124
30773
|
}
|
|
30125
30774
|
async function needsCursorRegeneration(projectRoot) {
|
|
30126
|
-
const cursorDir =
|
|
30127
|
-
const routerPath =
|
|
30775
|
+
const cursorDir = path62.join(projectRoot, ".cursor");
|
|
30776
|
+
const routerPath = path62.join(cursorDir, "rules", "prjct.mdc");
|
|
30128
30777
|
return await fileExists(cursorDir) && !await fileExists(routerPath);
|
|
30129
30778
|
}
|
|
30130
30779
|
async function installWindsurfProject(projectRoot) {
|
|
@@ -30135,26 +30784,26 @@ async function installWindsurfProject(projectRoot) {
|
|
|
30135
30784
|
gitignoreUpdated: false
|
|
30136
30785
|
};
|
|
30137
30786
|
try {
|
|
30138
|
-
const windsurfDir =
|
|
30139
|
-
const rulesDir =
|
|
30140
|
-
const workflowsDir =
|
|
30141
|
-
const routerDest =
|
|
30142
|
-
const routerSource =
|
|
30143
|
-
const windsurfWorkflowsSource =
|
|
30144
|
-
await
|
|
30145
|
-
await
|
|
30787
|
+
const windsurfDir = path62.join(projectRoot, ".windsurf");
|
|
30788
|
+
const rulesDir = path62.join(windsurfDir, "rules");
|
|
30789
|
+
const workflowsDir = path62.join(windsurfDir, "workflows");
|
|
30790
|
+
const routerDest = path62.join(rulesDir, "prjct.md");
|
|
30791
|
+
const routerSource = path62.join(PACKAGE_ROOT, "templates", "windsurf", "router.md");
|
|
30792
|
+
const windsurfWorkflowsSource = path62.join(PACKAGE_ROOT, "templates", "windsurf", "workflows");
|
|
30793
|
+
await fs58.mkdir(rulesDir, { recursive: true });
|
|
30794
|
+
await fs58.mkdir(workflowsDir, { recursive: true });
|
|
30146
30795
|
if (await fileExists(routerSource)) {
|
|
30147
|
-
await
|
|
30796
|
+
await fs58.copyFile(routerSource, routerDest);
|
|
30148
30797
|
result.rulesCreated = true;
|
|
30149
30798
|
}
|
|
30150
30799
|
if (await fileExists(windsurfWorkflowsSource)) {
|
|
30151
|
-
const workflowFiles = (await
|
|
30800
|
+
const workflowFiles = (await fs58.readdir(windsurfWorkflowsSource)).filter(
|
|
30152
30801
|
(f) => f.endsWith(".md")
|
|
30153
30802
|
);
|
|
30154
30803
|
for (const file of workflowFiles) {
|
|
30155
|
-
const src =
|
|
30156
|
-
const dest =
|
|
30157
|
-
await
|
|
30804
|
+
const src = path62.join(windsurfWorkflowsSource, file);
|
|
30805
|
+
const dest = path62.join(workflowsDir, file);
|
|
30806
|
+
await fs58.copyFile(src, dest);
|
|
30158
30807
|
}
|
|
30159
30808
|
result.workflowsCreated = workflowFiles.length > 0;
|
|
30160
30809
|
}
|
|
@@ -30168,7 +30817,7 @@ async function installWindsurfProject(projectRoot) {
|
|
|
30168
30817
|
}
|
|
30169
30818
|
async function addWindsurfToGitignore(projectRoot) {
|
|
30170
30819
|
try {
|
|
30171
|
-
const gitignorePath =
|
|
30820
|
+
const gitignorePath = path62.join(projectRoot, ".gitignore");
|
|
30172
30821
|
const entriesToAdd = [
|
|
30173
30822
|
"# prjct Windsurf routers (regenerated per-developer)",
|
|
30174
30823
|
".windsurf/rules/prjct.md",
|
|
@@ -30183,7 +30832,7 @@ async function addWindsurfToGitignore(projectRoot) {
|
|
|
30183
30832
|
let content = "";
|
|
30184
30833
|
let configExists = false;
|
|
30185
30834
|
try {
|
|
30186
|
-
content = await
|
|
30835
|
+
content = await fs58.readFile(gitignorePath, "utf-8");
|
|
30187
30836
|
configExists = true;
|
|
30188
30837
|
} catch (error) {
|
|
30189
30838
|
if (!isNotFoundError(error)) {
|
|
@@ -30198,7 +30847,7 @@ async function addWindsurfToGitignore(projectRoot) {
|
|
|
30198
30847
|
${entriesToAdd.join("\n")}
|
|
30199
30848
|
` : `${entriesToAdd.join("\n")}
|
|
30200
30849
|
`;
|
|
30201
|
-
await
|
|
30850
|
+
await fs58.writeFile(gitignorePath, newContent, "utf-8");
|
|
30202
30851
|
return true;
|
|
30203
30852
|
} catch (error) {
|
|
30204
30853
|
logger_default.warn(`Gitignore update warning: ${getErrorMessage2(error)}`);
|
|
@@ -30206,32 +30855,32 @@ ${entriesToAdd.join("\n")}
|
|
|
30206
30855
|
}
|
|
30207
30856
|
}
|
|
30208
30857
|
async function hasWindsurfProject(projectRoot) {
|
|
30209
|
-
return await fileExists(
|
|
30858
|
+
return await fileExists(path62.join(projectRoot, ".windsurf"));
|
|
30210
30859
|
}
|
|
30211
30860
|
async function needsWindsurfRegeneration(projectRoot) {
|
|
30212
|
-
const windsurfDir =
|
|
30213
|
-
const routerPath =
|
|
30861
|
+
const windsurfDir = path62.join(projectRoot, ".windsurf");
|
|
30862
|
+
const routerPath = path62.join(windsurfDir, "rules", "prjct.md");
|
|
30214
30863
|
return await fileExists(windsurfDir) && !await fileExists(routerPath);
|
|
30215
30864
|
}
|
|
30216
30865
|
async function migrateProjectsCliVersion() {
|
|
30217
30866
|
try {
|
|
30218
|
-
const projectsDir =
|
|
30867
|
+
const projectsDir = path62.join(os18.homedir(), ".prjct-cli", "projects");
|
|
30219
30868
|
if (!await fileExists(projectsDir)) {
|
|
30220
30869
|
return;
|
|
30221
30870
|
}
|
|
30222
|
-
const projectDirs = (await
|
|
30871
|
+
const projectDirs = (await fs58.readdir(projectsDir, { withFileTypes: true })).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
30223
30872
|
let migrated = 0;
|
|
30224
30873
|
for (const projectId of projectDirs) {
|
|
30225
|
-
const projectJsonPath =
|
|
30874
|
+
const projectJsonPath = path62.join(projectsDir, projectId, "project.json");
|
|
30226
30875
|
if (!await fileExists(projectJsonPath)) {
|
|
30227
30876
|
continue;
|
|
30228
30877
|
}
|
|
30229
30878
|
try {
|
|
30230
|
-
const content = await
|
|
30879
|
+
const content = await fs58.readFile(projectJsonPath, "utf8");
|
|
30231
30880
|
const project = JSON.parse(content);
|
|
30232
30881
|
if (project.cliVersion !== VERSION) {
|
|
30233
30882
|
project.cliVersion = VERSION;
|
|
30234
|
-
await
|
|
30883
|
+
await fs58.writeFile(projectJsonPath, JSON.stringify(project, null, 2));
|
|
30235
30884
|
migrated++;
|
|
30236
30885
|
}
|
|
30237
30886
|
} catch (error) {
|
|
@@ -30253,7 +30902,7 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
|
|
|
30253
30902
|
let settings = {};
|
|
30254
30903
|
if (await fileExists(settingsPath)) {
|
|
30255
30904
|
try {
|
|
30256
|
-
settings = JSON.parse(await
|
|
30905
|
+
settings = JSON.parse(await fs58.readFile(settingsPath, "utf8"));
|
|
30257
30906
|
} catch (error) {
|
|
30258
30907
|
if (!(error instanceof SyntaxError)) {
|
|
30259
30908
|
throw error;
|
|
@@ -30261,42 +30910,42 @@ async function ensureStatusLineSettings(settingsPath, statusLinePath) {
|
|
|
30261
30910
|
}
|
|
30262
30911
|
}
|
|
30263
30912
|
settings.statusLine = { type: "command", command: statusLinePath };
|
|
30264
|
-
await
|
|
30913
|
+
await fs58.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
30265
30914
|
}
|
|
30266
30915
|
async function installStatusLine() {
|
|
30267
30916
|
try {
|
|
30268
|
-
const claudeDir =
|
|
30269
|
-
const settingsPath =
|
|
30270
|
-
const claudeStatusLinePath =
|
|
30271
|
-
const prjctStatusLineDir =
|
|
30272
|
-
const prjctStatusLinePath =
|
|
30273
|
-
const prjctThemesDir =
|
|
30274
|
-
const prjctLibDir =
|
|
30275
|
-
const prjctComponentsDir =
|
|
30276
|
-
const prjctConfigPath =
|
|
30277
|
-
const assetsDir =
|
|
30278
|
-
const sourceScript =
|
|
30279
|
-
const sourceThemeDir =
|
|
30280
|
-
const sourceLibDir =
|
|
30281
|
-
const sourceComponentsDir =
|
|
30282
|
-
const sourceConfigPath =
|
|
30917
|
+
const claudeDir = path62.join(os18.homedir(), ".claude");
|
|
30918
|
+
const settingsPath = path62.join(claudeDir, "settings.json");
|
|
30919
|
+
const claudeStatusLinePath = path62.join(claudeDir, "prjct-statusline.sh");
|
|
30920
|
+
const prjctStatusLineDir = path62.join(os18.homedir(), ".prjct-cli", "statusline");
|
|
30921
|
+
const prjctStatusLinePath = path62.join(prjctStatusLineDir, "statusline.sh");
|
|
30922
|
+
const prjctThemesDir = path62.join(prjctStatusLineDir, "themes");
|
|
30923
|
+
const prjctLibDir = path62.join(prjctStatusLineDir, "lib");
|
|
30924
|
+
const prjctComponentsDir = path62.join(prjctStatusLineDir, "components");
|
|
30925
|
+
const prjctConfigPath = path62.join(prjctStatusLineDir, "config.json");
|
|
30926
|
+
const assetsDir = path62.join(PACKAGE_ROOT, "assets", "statusline");
|
|
30927
|
+
const sourceScript = path62.join(assetsDir, "statusline.sh");
|
|
30928
|
+
const sourceThemeDir = path62.join(assetsDir, "themes");
|
|
30929
|
+
const sourceLibDir = path62.join(assetsDir, "lib");
|
|
30930
|
+
const sourceComponentsDir = path62.join(assetsDir, "components");
|
|
30931
|
+
const sourceConfigPath = path62.join(assetsDir, "default-config.json");
|
|
30283
30932
|
if (!await fileExists(claudeDir)) {
|
|
30284
|
-
await
|
|
30933
|
+
await fs58.mkdir(claudeDir, { recursive: true });
|
|
30285
30934
|
}
|
|
30286
30935
|
if (!await fileExists(prjctStatusLineDir)) {
|
|
30287
|
-
await
|
|
30936
|
+
await fs58.mkdir(prjctStatusLineDir, { recursive: true });
|
|
30288
30937
|
}
|
|
30289
30938
|
if (!await fileExists(prjctThemesDir)) {
|
|
30290
|
-
await
|
|
30939
|
+
await fs58.mkdir(prjctThemesDir, { recursive: true });
|
|
30291
30940
|
}
|
|
30292
30941
|
if (!await fileExists(prjctLibDir)) {
|
|
30293
|
-
await
|
|
30942
|
+
await fs58.mkdir(prjctLibDir, { recursive: true });
|
|
30294
30943
|
}
|
|
30295
30944
|
if (!await fileExists(prjctComponentsDir)) {
|
|
30296
|
-
await
|
|
30945
|
+
await fs58.mkdir(prjctComponentsDir, { recursive: true });
|
|
30297
30946
|
}
|
|
30298
30947
|
if (await fileExists(prjctStatusLinePath)) {
|
|
30299
|
-
const existingContent = await
|
|
30948
|
+
const existingContent = await fs58.readFile(prjctStatusLinePath, "utf8");
|
|
30300
30949
|
if (existingContent.includes("CLI_VERSION=")) {
|
|
30301
30950
|
const versionMatch = existingContent.match(/CLI_VERSION="([^"]*)"/);
|
|
30302
30951
|
if (versionMatch && versionMatch[1] !== VERSION) {
|
|
@@ -30304,7 +30953,7 @@ async function installStatusLine() {
|
|
|
30304
30953
|
/CLI_VERSION="[^"]*"/,
|
|
30305
30954
|
`CLI_VERSION="${VERSION}"`
|
|
30306
30955
|
);
|
|
30307
|
-
await
|
|
30956
|
+
await fs58.writeFile(prjctStatusLinePath, updatedContent, { mode: 493 });
|
|
30308
30957
|
}
|
|
30309
30958
|
await installStatusLineModules(sourceLibDir, prjctLibDir);
|
|
30310
30959
|
await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
|
|
@@ -30314,21 +30963,21 @@ async function installStatusLine() {
|
|
|
30314
30963
|
}
|
|
30315
30964
|
}
|
|
30316
30965
|
if (await fileExists(sourceScript)) {
|
|
30317
|
-
let scriptContent = await
|
|
30966
|
+
let scriptContent = await fs58.readFile(sourceScript, "utf8");
|
|
30318
30967
|
scriptContent = scriptContent.replace(/CLI_VERSION="[^"]*"/, `CLI_VERSION="${VERSION}"`);
|
|
30319
|
-
await
|
|
30968
|
+
await fs58.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
|
|
30320
30969
|
await installStatusLineModules(sourceLibDir, prjctLibDir);
|
|
30321
30970
|
await installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
|
|
30322
30971
|
if (await fileExists(sourceThemeDir)) {
|
|
30323
|
-
const themes = await
|
|
30972
|
+
const themes = await fs58.readdir(sourceThemeDir);
|
|
30324
30973
|
for (const theme of themes) {
|
|
30325
|
-
const src =
|
|
30326
|
-
const dest =
|
|
30327
|
-
await
|
|
30974
|
+
const src = path62.join(sourceThemeDir, theme);
|
|
30975
|
+
const dest = path62.join(prjctThemesDir, theme);
|
|
30976
|
+
await fs58.copyFile(src, dest);
|
|
30328
30977
|
}
|
|
30329
30978
|
}
|
|
30330
30979
|
if (!await fileExists(prjctConfigPath) && await fileExists(sourceConfigPath)) {
|
|
30331
|
-
await
|
|
30980
|
+
await fs58.copyFile(sourceConfigPath, prjctConfigPath);
|
|
30332
30981
|
}
|
|
30333
30982
|
} else {
|
|
30334
30983
|
const scriptContent = `#!/bin/bash
|
|
@@ -30363,7 +31012,7 @@ if [ -f "$CONFIG" ]; then
|
|
|
30363
31012
|
fi
|
|
30364
31013
|
echo "prjct"
|
|
30365
31014
|
`;
|
|
30366
|
-
await
|
|
31015
|
+
await fs58.writeFile(prjctStatusLinePath, scriptContent, { mode: 493 });
|
|
30367
31016
|
}
|
|
30368
31017
|
await ensureStatusLineSymlink(claudeStatusLinePath, prjctStatusLinePath);
|
|
30369
31018
|
await ensureStatusLineSettings(settingsPath, claudeStatusLinePath);
|
|
@@ -30375,10 +31024,10 @@ echo "prjct"
|
|
|
30375
31024
|
}
|
|
30376
31025
|
async function installContext7MCP() {
|
|
30377
31026
|
try {
|
|
30378
|
-
const claudeDir =
|
|
30379
|
-
const mcpConfigPath =
|
|
31027
|
+
const claudeDir = path62.join(os18.homedir(), ".claude");
|
|
31028
|
+
const mcpConfigPath = path62.join(claudeDir, "mcp.json");
|
|
30380
31029
|
if (!await fileExists(claudeDir)) {
|
|
30381
|
-
await
|
|
31030
|
+
await fs58.mkdir(claudeDir, { recursive: true });
|
|
30382
31031
|
}
|
|
30383
31032
|
const context7Config = {
|
|
30384
31033
|
mcpServers: {
|
|
@@ -30389,16 +31038,16 @@ async function installContext7MCP() {
|
|
|
30389
31038
|
}
|
|
30390
31039
|
};
|
|
30391
31040
|
if (await fileExists(mcpConfigPath)) {
|
|
30392
|
-
const existingContent = await
|
|
31041
|
+
const existingContent = await fs58.readFile(mcpConfigPath, "utf-8");
|
|
30393
31042
|
const existingConfig = JSON.parse(existingContent);
|
|
30394
31043
|
if (existingConfig.mcpServers?.context7) {
|
|
30395
31044
|
return;
|
|
30396
31045
|
}
|
|
30397
31046
|
existingConfig.mcpServers = existingConfig.mcpServers || {};
|
|
30398
31047
|
existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
|
|
30399
|
-
await
|
|
31048
|
+
await fs58.writeFile(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
|
|
30400
31049
|
} else {
|
|
30401
|
-
await
|
|
31050
|
+
await fs58.writeFile(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
|
|
30402
31051
|
}
|
|
30403
31052
|
} catch (error) {
|
|
30404
31053
|
logger_default.warn(`Context7 MCP setup warning: ${getErrorMessage2(error)}`);
|
|
@@ -30408,34 +31057,34 @@ async function installStatusLineModules(sourceDir, destDir) {
|
|
|
30408
31057
|
if (!await fileExists(sourceDir)) {
|
|
30409
31058
|
return;
|
|
30410
31059
|
}
|
|
30411
|
-
const files = await
|
|
31060
|
+
const files = await fs58.readdir(sourceDir);
|
|
30412
31061
|
for (const file of files) {
|
|
30413
31062
|
if (file.endsWith(".sh")) {
|
|
30414
|
-
const src =
|
|
30415
|
-
const dest =
|
|
30416
|
-
await
|
|
30417
|
-
await
|
|
31063
|
+
const src = path62.join(sourceDir, file);
|
|
31064
|
+
const dest = path62.join(destDir, file);
|
|
31065
|
+
await fs58.copyFile(src, dest);
|
|
31066
|
+
await fs58.chmod(dest, 493);
|
|
30418
31067
|
}
|
|
30419
31068
|
}
|
|
30420
31069
|
}
|
|
30421
31070
|
async function ensureStatusLineSymlink(linkPath, targetPath) {
|
|
30422
31071
|
try {
|
|
30423
31072
|
if (await fileExists(linkPath)) {
|
|
30424
|
-
const stats = await
|
|
31073
|
+
const stats = await fs58.lstat(linkPath);
|
|
30425
31074
|
if (stats.isSymbolicLink()) {
|
|
30426
|
-
const existingTarget = await
|
|
31075
|
+
const existingTarget = await fs58.readlink(linkPath);
|
|
30427
31076
|
if (existingTarget === targetPath) {
|
|
30428
31077
|
return;
|
|
30429
31078
|
}
|
|
30430
31079
|
}
|
|
30431
|
-
await
|
|
31080
|
+
await fs58.unlink(linkPath);
|
|
30432
31081
|
}
|
|
30433
|
-
await
|
|
31082
|
+
await fs58.symlink(targetPath, linkPath);
|
|
30434
31083
|
} catch (_error) {
|
|
30435
31084
|
try {
|
|
30436
31085
|
if (await fileExists(targetPath)) {
|
|
30437
|
-
await
|
|
30438
|
-
await
|
|
31086
|
+
await fs58.copyFile(targetPath, linkPath);
|
|
31087
|
+
await fs58.chmod(linkPath, 493);
|
|
30439
31088
|
}
|
|
30440
31089
|
} catch (copyError) {
|
|
30441
31090
|
if (!isNotFoundError(copyError)) {
|
|
@@ -30850,7 +31499,7 @@ var init_registry2 = __esm({
|
|
|
30850
31499
|
});
|
|
30851
31500
|
|
|
30852
31501
|
// core/commands/analytics.ts
|
|
30853
|
-
import
|
|
31502
|
+
import path63 from "node:path";
|
|
30854
31503
|
var AnalyticsCommands;
|
|
30855
31504
|
var init_analytics = __esm({
|
|
30856
31505
|
"core/commands/analytics.ts"() {
|
|
@@ -30877,7 +31526,7 @@ var init_analytics = __esm({
|
|
|
30877
31526
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
30878
31527
|
return { success: false, error: "No project ID found" };
|
|
30879
31528
|
}
|
|
30880
|
-
const projectName =
|
|
31529
|
+
const projectName = path63.basename(projectPath);
|
|
30881
31530
|
const currentTask = await stateStorage.getCurrentTask(projectId);
|
|
30882
31531
|
const queueTasks = await queueStorage.getActiveTasks(projectId);
|
|
30883
31532
|
const shipped = await shippedStorage.getRecent(projectId, 5);
|
|
@@ -31129,8 +31778,8 @@ ${"\u2550".repeat(50)}
|
|
|
31129
31778
|
});
|
|
31130
31779
|
|
|
31131
31780
|
// core/commands/context.ts
|
|
31132
|
-
import
|
|
31133
|
-
import
|
|
31781
|
+
import fs59 from "node:fs/promises";
|
|
31782
|
+
import path64 from "node:path";
|
|
31134
31783
|
var ContextCommands, contextCommands;
|
|
31135
31784
|
var init_context = __esm({
|
|
31136
31785
|
"core/commands/context.ts"() {
|
|
@@ -31256,8 +31905,8 @@ var init_context = __esm({
|
|
|
31256
31905
|
*/
|
|
31257
31906
|
async loadRepoAnalysis(globalPath) {
|
|
31258
31907
|
try {
|
|
31259
|
-
const analysisPath =
|
|
31260
|
-
const content = await
|
|
31908
|
+
const analysisPath = path64.join(globalPath, "analysis", "repo-analysis.json");
|
|
31909
|
+
const content = await fs59.readFile(analysisPath, "utf-8");
|
|
31261
31910
|
const data = JSON.parse(content);
|
|
31262
31911
|
return {
|
|
31263
31912
|
ecosystem: data.ecosystem || "unknown",
|
|
@@ -31276,7 +31925,7 @@ var init_context = __esm({
|
|
|
31276
31925
|
});
|
|
31277
31926
|
|
|
31278
31927
|
// core/commands/cleanup.ts
|
|
31279
|
-
import
|
|
31928
|
+
import path65 from "node:path";
|
|
31280
31929
|
async function cleanupMemory(projectPath) {
|
|
31281
31930
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
31282
31931
|
const results = { rotated: [], totalSize: 0, freedSpace: 0 };
|
|
@@ -31292,7 +31941,7 @@ async function cleanupMemory(projectPath) {
|
|
|
31292
31941
|
results.totalSize += sizeMB;
|
|
31293
31942
|
const rotated = await jsonl_helper_exports.rotateJsonLinesIfNeeded(filePath, 10);
|
|
31294
31943
|
if (rotated) {
|
|
31295
|
-
results.rotated.push(
|
|
31944
|
+
results.rotated.push(path65.basename(filePath));
|
|
31296
31945
|
results.freedSpace += sizeMB;
|
|
31297
31946
|
}
|
|
31298
31947
|
}
|
|
@@ -31399,7 +32048,7 @@ var init_cleanup = __esm({
|
|
|
31399
32048
|
});
|
|
31400
32049
|
|
|
31401
32050
|
// core/commands/design.ts
|
|
31402
|
-
import
|
|
32051
|
+
import path66 from "node:path";
|
|
31403
32052
|
async function design(target = null, options = {}, projectPath = process.cwd()) {
|
|
31404
32053
|
try {
|
|
31405
32054
|
const designType = options.type || "architecture";
|
|
@@ -31411,7 +32060,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
|
|
|
31411
32060
|
const designTarget = target || "system";
|
|
31412
32061
|
output_default.spin(`designing ${designType}...`);
|
|
31413
32062
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
31414
|
-
const designsPath =
|
|
32063
|
+
const designsPath = path66.join(
|
|
31415
32064
|
path_manager_default.getGlobalProjectPath(projectId),
|
|
31416
32065
|
"planning",
|
|
31417
32066
|
"designs"
|
|
@@ -31451,7 +32100,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
|
|
|
31451
32100
|
break;
|
|
31452
32101
|
}
|
|
31453
32102
|
const designFileName = `${designType}-${designTarget.toLowerCase().replace(/\s+/g, "-")}.md`;
|
|
31454
|
-
const designFilePath =
|
|
32103
|
+
const designFilePath = path66.join(designsPath, designFileName);
|
|
31455
32104
|
await file_helper_exports.writeFile(designFilePath, designContent);
|
|
31456
32105
|
await memoryService.log(projectPath, "design_created", {
|
|
31457
32106
|
type: designType,
|
|
@@ -31476,7 +32125,7 @@ var init_design = __esm({
|
|
|
31476
32125
|
});
|
|
31477
32126
|
|
|
31478
32127
|
// core/commands/snapshots.ts
|
|
31479
|
-
import
|
|
32128
|
+
import path67 from "node:path";
|
|
31480
32129
|
async function recover(projectPath = process.cwd()) {
|
|
31481
32130
|
try {
|
|
31482
32131
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
@@ -31528,7 +32177,7 @@ async function undo(projectPath = process.cwd()) {
|
|
|
31528
32177
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
31529
32178
|
return { success: false, error: "No project ID found" };
|
|
31530
32179
|
}
|
|
31531
|
-
const snapshotsPath =
|
|
32180
|
+
const snapshotsPath = path67.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
31532
32181
|
await file_helper_exports.ensureDir(snapshotsPath);
|
|
31533
32182
|
const { execSync: execSync5 } = await import("node:child_process");
|
|
31534
32183
|
try {
|
|
@@ -31546,7 +32195,7 @@ async function undo(projectPath = process.cwd()) {
|
|
|
31546
32195
|
cwd: projectPath,
|
|
31547
32196
|
encoding: "utf-8"
|
|
31548
32197
|
});
|
|
31549
|
-
const snapshotFile =
|
|
32198
|
+
const snapshotFile = path67.join(snapshotsPath, "history.json");
|
|
31550
32199
|
let history2 = { snapshots: [], current: -1 };
|
|
31551
32200
|
try {
|
|
31552
32201
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -31586,8 +32235,8 @@ async function redo(projectPath = process.cwd()) {
|
|
|
31586
32235
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
31587
32236
|
return { success: false, error: "No project ID found" };
|
|
31588
32237
|
}
|
|
31589
|
-
const snapshotsPath =
|
|
31590
|
-
const snapshotFile =
|
|
32238
|
+
const snapshotsPath = path67.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
32239
|
+
const snapshotFile = path67.join(snapshotsPath, "history.json");
|
|
31591
32240
|
let history2;
|
|
31592
32241
|
try {
|
|
31593
32242
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -31646,8 +32295,8 @@ async function history(projectPath = process.cwd()) {
|
|
|
31646
32295
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
31647
32296
|
return { success: false, error: "No project ID found" };
|
|
31648
32297
|
}
|
|
31649
|
-
const snapshotsPath =
|
|
31650
|
-
const snapshotFile =
|
|
32298
|
+
const snapshotsPath = path67.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
32299
|
+
const snapshotFile = path67.join(snapshotsPath, "history.json");
|
|
31651
32300
|
let snapshotHistory;
|
|
31652
32301
|
try {
|
|
31653
32302
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -31850,8 +32499,8 @@ ${chalk16.cyan("Performance Report")} ${chalk16.dim(`(last ${days} days)`)}`);
|
|
|
31850
32499
|
});
|
|
31851
32500
|
|
|
31852
32501
|
// core/commands/setup.ts
|
|
31853
|
-
import
|
|
31854
|
-
import
|
|
32502
|
+
import fs60 from "node:fs/promises";
|
|
32503
|
+
import path68 from "node:path";
|
|
31855
32504
|
import chalk17 from "chalk";
|
|
31856
32505
|
var SetupCommands;
|
|
31857
32506
|
var init_setup2 = __esm({
|
|
@@ -31980,7 +32629,7 @@ Please install it first:
|
|
|
31980
32629
|
try {
|
|
31981
32630
|
const claudeDir = path_manager_default.getClaudeDir();
|
|
31982
32631
|
const settingsPath = path_manager_default.getClaudeSettingsPath();
|
|
31983
|
-
const statusLinePath =
|
|
32632
|
+
const statusLinePath = path68.join(claudeDir, "prjct-statusline.sh");
|
|
31984
32633
|
const scriptContent = `#!/bin/bash
|
|
31985
32634
|
# prjct Status Line for Claude Code
|
|
31986
32635
|
# Shows version update notifications and current task
|
|
@@ -32038,11 +32687,11 @@ fi
|
|
|
32038
32687
|
# Default: show prjct branding
|
|
32039
32688
|
echo "\u26A1 prjct"
|
|
32040
32689
|
`;
|
|
32041
|
-
await
|
|
32690
|
+
await fs60.writeFile(statusLinePath, scriptContent, { mode: 493 });
|
|
32042
32691
|
let settings = {};
|
|
32043
32692
|
if (await fileExists(settingsPath)) {
|
|
32044
32693
|
try {
|
|
32045
|
-
settings = JSON.parse(await
|
|
32694
|
+
settings = JSON.parse(await fs60.readFile(settingsPath, "utf8"));
|
|
32046
32695
|
} catch (_error) {
|
|
32047
32696
|
}
|
|
32048
32697
|
}
|
|
@@ -32050,7 +32699,7 @@ echo "\u26A1 prjct"
|
|
|
32050
32699
|
type: "command",
|
|
32051
32700
|
command: statusLinePath
|
|
32052
32701
|
};
|
|
32053
|
-
await
|
|
32702
|
+
await fs60.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
32054
32703
|
return { success: true };
|
|
32055
32704
|
} catch (error) {
|
|
32056
32705
|
return { success: false, error: getErrorMessage2(error) };
|
|
@@ -32106,18 +32755,18 @@ echo "\u26A1 prjct"
|
|
|
32106
32755
|
});
|
|
32107
32756
|
|
|
32108
32757
|
// core/utils/project-commands.ts
|
|
32109
|
-
import
|
|
32758
|
+
import path69 from "node:path";
|
|
32110
32759
|
async function detectPackageManager(projectPath, pkg) {
|
|
32111
32760
|
const declared = pkg?.packageManager?.trim().toLowerCase();
|
|
32112
32761
|
if (declared?.startsWith("pnpm@")) return "pnpm";
|
|
32113
32762
|
if (declared?.startsWith("yarn@")) return "yarn";
|
|
32114
32763
|
if (declared?.startsWith("bun@")) return "bun";
|
|
32115
32764
|
if (declared?.startsWith("npm@")) return "npm";
|
|
32116
|
-
if (await fileExists2(
|
|
32117
|
-
if (await fileExists2(
|
|
32118
|
-
if (await fileExists2(
|
|
32119
|
-
if (await fileExists2(
|
|
32120
|
-
if (await fileExists2(
|
|
32765
|
+
if (await fileExists2(path69.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
|
|
32766
|
+
if (await fileExists2(path69.join(projectPath, "yarn.lock"))) return "yarn";
|
|
32767
|
+
if (await fileExists2(path69.join(projectPath, "bun.lockb"))) return "bun";
|
|
32768
|
+
if (await fileExists2(path69.join(projectPath, "bun.lock"))) return "bun";
|
|
32769
|
+
if (await fileExists2(path69.join(projectPath, "package-lock.json"))) return "npm";
|
|
32121
32770
|
return "npm";
|
|
32122
32771
|
}
|
|
32123
32772
|
function pmRun(pm, scriptName) {
|
|
@@ -32133,7 +32782,7 @@ function pmTest(pm) {
|
|
|
32133
32782
|
return "npm test";
|
|
32134
32783
|
}
|
|
32135
32784
|
async function detectProjectCommands(projectPath) {
|
|
32136
|
-
const pkgPath =
|
|
32785
|
+
const pkgPath = path69.join(projectPath, "package.json");
|
|
32137
32786
|
const pkg = await readJson(pkgPath, null);
|
|
32138
32787
|
if (pkg) {
|
|
32139
32788
|
const pm = await detectPackageManager(projectPath, pkg);
|
|
@@ -32150,27 +32799,27 @@ async function detectProjectCommands(projectPath) {
|
|
|
32150
32799
|
}
|
|
32151
32800
|
return result;
|
|
32152
32801
|
}
|
|
32153
|
-
if (await fileExists2(
|
|
32802
|
+
if (await fileExists2(path69.join(projectPath, "pytest.ini"))) {
|
|
32154
32803
|
return { stack: "python", test: { tool: "pytest", command: "pytest" } };
|
|
32155
32804
|
}
|
|
32156
|
-
const pyproject = await readFile(
|
|
32805
|
+
const pyproject = await readFile(path69.join(projectPath, "pyproject.toml"), "");
|
|
32157
32806
|
if (pyproject.includes("[tool.pytest") || pyproject.includes("pytest")) {
|
|
32158
32807
|
return { stack: "python", test: { tool: "pytest", command: "pytest" } };
|
|
32159
32808
|
}
|
|
32160
|
-
if (await fileExists2(
|
|
32809
|
+
if (await fileExists2(path69.join(projectPath, "Cargo.toml"))) {
|
|
32161
32810
|
return { stack: "rust", test: { tool: "cargo", command: "cargo test" } };
|
|
32162
32811
|
}
|
|
32163
|
-
if (await fileExists2(
|
|
32812
|
+
if (await fileExists2(path69.join(projectPath, "go.mod"))) {
|
|
32164
32813
|
return { stack: "go", test: { tool: "go", command: "go test ./..." } };
|
|
32165
32814
|
}
|
|
32166
32815
|
const files = await listFiles(projectPath);
|
|
32167
32816
|
if (files.some((f) => f.endsWith(".sln") || f.endsWith(".csproj") || f.endsWith(".fsproj"))) {
|
|
32168
32817
|
return { stack: "dotnet", test: { tool: "dotnet", command: "dotnet test" } };
|
|
32169
32818
|
}
|
|
32170
|
-
if (await fileExists2(
|
|
32819
|
+
if (await fileExists2(path69.join(projectPath, "pom.xml"))) {
|
|
32171
32820
|
return { stack: "java", test: { tool: "maven", command: "mvn test" } };
|
|
32172
32821
|
}
|
|
32173
|
-
if (await fileExists2(
|
|
32822
|
+
if (await fileExists2(path69.join(projectPath, "gradlew")) && (await fileExists2(path69.join(projectPath, "build.gradle")) || await fileExists2(path69.join(projectPath, "build.gradle.kts")))) {
|
|
32174
32823
|
return { stack: "java", test: { tool: "gradle", command: "./gradlew test" } };
|
|
32175
32824
|
}
|
|
32176
32825
|
return { stack: "unknown" };
|
|
@@ -32345,7 +32994,7 @@ var init_workflow_preferences = __esm({
|
|
|
32345
32994
|
});
|
|
32346
32995
|
|
|
32347
32996
|
// core/commands/shipping.ts
|
|
32348
|
-
import
|
|
32997
|
+
import path70 from "node:path";
|
|
32349
32998
|
var ShippingCommands;
|
|
32350
32999
|
var init_shipping = __esm({
|
|
32351
33000
|
"core/commands/shipping.ts"() {
|
|
@@ -32491,7 +33140,7 @@ ${result.stderr}`.trim();
|
|
|
32491
33140
|
*/
|
|
32492
33141
|
async _bumpVersion(projectPath) {
|
|
32493
33142
|
try {
|
|
32494
|
-
const pkgPath =
|
|
33143
|
+
const pkgPath = path70.join(projectPath, "package.json");
|
|
32495
33144
|
const pkg = await file_helper_exports.readJson(pkgPath, { version: "0.0.0" });
|
|
32496
33145
|
const oldVersion = pkg?.version || "0.0.0";
|
|
32497
33146
|
const [major, minor, patch] = oldVersion.split(".").map(Number);
|
|
@@ -32513,7 +33162,7 @@ ${result.stderr}`.trim();
|
|
|
32513
33162
|
*/
|
|
32514
33163
|
async _updateChangelog(feature, version, projectPath) {
|
|
32515
33164
|
try {
|
|
32516
|
-
const changelogPath =
|
|
33165
|
+
const changelogPath = path70.join(projectPath, "CHANGELOG.md");
|
|
32517
33166
|
const changelog = await file_helper_exports.readFile(changelogPath, "# Changelog\n\n");
|
|
32518
33167
|
const entry = `## [${version}] - ${date_helper_exports.formatDate(/* @__PURE__ */ new Date())}
|
|
32519
33168
|
|
|
@@ -33557,11 +34206,11 @@ var init_linear = __esm({
|
|
|
33557
34206
|
});
|
|
33558
34207
|
|
|
33559
34208
|
// core/utils/project-credentials.ts
|
|
33560
|
-
import
|
|
34209
|
+
import fs61 from "node:fs/promises";
|
|
33561
34210
|
import os19 from "node:os";
|
|
33562
|
-
import
|
|
34211
|
+
import path71 from "node:path";
|
|
33563
34212
|
function getCredentialsPath(projectId) {
|
|
33564
|
-
return
|
|
34213
|
+
return path71.join(os19.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
|
|
33565
34214
|
}
|
|
33566
34215
|
async function getProjectCredentials(projectId) {
|
|
33567
34216
|
const credPath = getCredentialsPath(projectId);
|
|
@@ -33569,7 +34218,7 @@ async function getProjectCredentials(projectId) {
|
|
|
33569
34218
|
return {};
|
|
33570
34219
|
}
|
|
33571
34220
|
try {
|
|
33572
|
-
return JSON.parse(await
|
|
34221
|
+
return JSON.parse(await fs61.readFile(credPath, "utf-8"));
|
|
33573
34222
|
} catch (error) {
|
|
33574
34223
|
console.error("[project-credentials] Failed to read credentials:", getErrorMessage2(error));
|
|
33575
34224
|
return {};
|
|
@@ -34241,7 +34890,7 @@ var require_package = __commonJS({
|
|
|
34241
34890
|
"package.json"(exports, module) {
|
|
34242
34891
|
module.exports = {
|
|
34243
34892
|
name: "prjct-cli",
|
|
34244
|
-
version: "1.
|
|
34893
|
+
version: "1.21.0",
|
|
34245
34894
|
description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
|
|
34246
34895
|
main: "core/index.ts",
|
|
34247
34896
|
bin: {
|
|
@@ -34348,7 +34997,7 @@ var require_package = __commonJS({
|
|
|
34348
34997
|
// core/index.ts
|
|
34349
34998
|
var core_exports = {};
|
|
34350
34999
|
import os20 from "node:os";
|
|
34351
|
-
import
|
|
35000
|
+
import path72 from "node:path";
|
|
34352
35001
|
import chalk20 from "chalk";
|
|
34353
35002
|
async function main() {
|
|
34354
35003
|
const [commandName, ...rawArgs] = process.argv.slice(2);
|
|
@@ -34457,7 +35106,10 @@ async function main() {
|
|
|
34457
35106
|
full: options.full === true
|
|
34458
35107
|
}), "sync"),
|
|
34459
35108
|
seal: /* @__PURE__ */ __name(() => commands.seal(process.cwd(), { json: options.json === true }), "seal"),
|
|
34460
|
-
verify: /* @__PURE__ */ __name(() => commands.verify(process.cwd(), {
|
|
35109
|
+
verify: /* @__PURE__ */ __name(() => commands.verify(process.cwd(), {
|
|
35110
|
+
json: options.json === true,
|
|
35111
|
+
semantic: options.semantic === true
|
|
35112
|
+
}), "verify"),
|
|
34461
35113
|
start: /* @__PURE__ */ __name(() => commands.start(), "start"),
|
|
34462
35114
|
// Context (for Claude templates)
|
|
34463
35115
|
context: /* @__PURE__ */ __name((p) => commands.context(p), "context")
|
|
@@ -34562,13 +35214,13 @@ function parseCommandArgs(_cmd, rawArgs) {
|
|
|
34562
35214
|
}
|
|
34563
35215
|
async function displayVersion(version) {
|
|
34564
35216
|
const detection = await detectAllProviders();
|
|
34565
|
-
const claudeCommandPath =
|
|
34566
|
-
const geminiCommandPath =
|
|
35217
|
+
const claudeCommandPath = path72.join(os20.homedir(), ".claude", "commands", "p.md");
|
|
35218
|
+
const geminiCommandPath = path72.join(os20.homedir(), ".gemini", "commands", "p.toml");
|
|
34567
35219
|
const [claudeConfigured, geminiConfigured, cursorConfigured, cursorExists] = await Promise.all([
|
|
34568
35220
|
fileExists(claudeCommandPath),
|
|
34569
35221
|
fileExists(geminiCommandPath),
|
|
34570
|
-
fileExists(
|
|
34571
|
-
fileExists(
|
|
35222
|
+
fileExists(path72.join(process.cwd(), ".cursor", "commands", "sync.md")),
|
|
35223
|
+
fileExists(path72.join(process.cwd(), ".cursor"))
|
|
34572
35224
|
]);
|
|
34573
35225
|
const antigravityDetection = await detectAntigravity();
|
|
34574
35226
|
console.log(`
|
|
@@ -34707,7 +35359,7 @@ init_ai_provider();
|
|
|
34707
35359
|
init_config_manager();
|
|
34708
35360
|
init_editors_config();
|
|
34709
35361
|
import os21 from "node:os";
|
|
34710
|
-
import
|
|
35362
|
+
import path73 from "node:path";
|
|
34711
35363
|
import chalk21 from "chalk";
|
|
34712
35364
|
|
|
34713
35365
|
// core/server/server.ts
|
|
@@ -35528,13 +36180,13 @@ async function checkRoutersInstalled() {
|
|
|
35528
36180
|
const home = os21.homedir();
|
|
35529
36181
|
const detection = await detectAllProviders();
|
|
35530
36182
|
if (detection.claude.installed) {
|
|
35531
|
-
const claudeRouter =
|
|
36183
|
+
const claudeRouter = path73.join(home, ".claude", "commands", "p.md");
|
|
35532
36184
|
if (!await fileExists(claudeRouter)) {
|
|
35533
36185
|
return false;
|
|
35534
36186
|
}
|
|
35535
36187
|
}
|
|
35536
36188
|
if (detection.gemini.installed) {
|
|
35537
|
-
const geminiRouter =
|
|
36189
|
+
const geminiRouter = path73.join(home, ".gemini", "commands", "p.toml");
|
|
35538
36190
|
if (!await fileExists(geminiRouter)) {
|
|
35539
36191
|
return false;
|
|
35540
36192
|
}
|
|
@@ -35675,7 +36327,7 @@ if (args[0] === "start" || args[0] === "setup") {
|
|
|
35675
36327
|
console.error('No prjct project found. Run "prjct init" first.');
|
|
35676
36328
|
process.exitCode = 1;
|
|
35677
36329
|
} else {
|
|
35678
|
-
const linearCliPath =
|
|
36330
|
+
const linearCliPath = path73.join(__dirname, "..", "core", "cli", "linear.ts");
|
|
35679
36331
|
const linearArgs = ["--project", projectId, ...args.slice(1)];
|
|
35680
36332
|
const child = spawn("bun", [linearCliPath, ...linearArgs], {
|
|
35681
36333
|
stdio: "inherit",
|
|
@@ -35702,12 +36354,12 @@ if (args[0] === "start" || args[0] === "setup") {
|
|
|
35702
36354
|
windsurfDetected,
|
|
35703
36355
|
windsurfConfigured
|
|
35704
36356
|
] = await Promise.all([
|
|
35705
|
-
fileExists(
|
|
35706
|
-
fileExists(
|
|
35707
|
-
fileExists(
|
|
35708
|
-
fileExists(
|
|
35709
|
-
fileExists(
|
|
35710
|
-
fileExists(
|
|
36357
|
+
fileExists(path73.join(home, ".claude", "commands", "p.md")),
|
|
36358
|
+
fileExists(path73.join(home, ".gemini", "commands", "p.toml")),
|
|
36359
|
+
fileExists(path73.join(cwd, ".cursor")),
|
|
36360
|
+
fileExists(path73.join(cwd, ".cursor", "rules", "prjct.mdc")),
|
|
36361
|
+
fileExists(path73.join(cwd, ".windsurf")),
|
|
36362
|
+
fileExists(path73.join(cwd, ".windsurf", "rules", "prjct.md"))
|
|
35711
36363
|
]);
|
|
35712
36364
|
console.log(`
|
|
35713
36365
|
${chalk21.cyan("p/")} prjct v${VERSION}
|
|
@@ -35746,7 +36398,7 @@ ${chalk21.dim("Run 'prjct init' to configure (Cursor/Windsurf IDE)")}
|
|
|
35746
36398
|
${chalk21.cyan("https://prjct.app")}
|
|
35747
36399
|
`);
|
|
35748
36400
|
} else {
|
|
35749
|
-
const configPath =
|
|
36401
|
+
const configPath = path73.join(os21.homedir(), ".prjct-cli", "config", "installed-editors.json");
|
|
35750
36402
|
const routersInstalled = await checkRoutersInstalled();
|
|
35751
36403
|
if (!await fileExists(configPath) || !routersInstalled) {
|
|
35752
36404
|
console.log(`
|