prjct-cli 0.60.2 → 0.62.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 +73 -0
- package/core/__tests__/services/dependency-validator.test.ts +175 -0
- package/core/infrastructure/setup.ts +24 -1
- package/core/services/dependency-validator.ts +318 -0
- package/core/services/git-analyzer.ts +28 -11
- package/core/services/local-state-generator.ts +158 -0
- package/core/services/skill-installer.ts +14 -1
- package/core/services/sync-service.ts +11 -0
- package/core/storage/state-storage.ts +3 -0
- package/dist/bin/prjct.mjs +708 -320
- package/dist/core/infrastructure/setup.js +274 -7
- 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) => (path59) => {
|
|
20
|
+
var fn = map[path59];
|
|
21
21
|
if (fn) return fn();
|
|
22
|
-
throw new Error("Module not found in bundle: " +
|
|
22
|
+
throw new Error("Module not found in bundle: " + path59);
|
|
23
23
|
};
|
|
24
24
|
var __esm = (fn, res) => function __init() {
|
|
25
25
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -4019,8 +4019,8 @@ function tryResolve(basePath, projectPath) {
|
|
|
4019
4019
|
for (const ext of extensions) {
|
|
4020
4020
|
const fullPath = basePath + ext;
|
|
4021
4021
|
try {
|
|
4022
|
-
const
|
|
4023
|
-
if (
|
|
4022
|
+
const fs50 = __require("node:fs");
|
|
4023
|
+
if (fs50.existsSync(fullPath) && fs50.statSync(fullPath).isFile()) {
|
|
4024
4024
|
return path12.relative(projectPath, fullPath);
|
|
4025
4025
|
}
|
|
4026
4026
|
} catch {
|
|
@@ -5203,11 +5203,11 @@ async function runSignaturesTool(args2, projectPath) {
|
|
|
5203
5203
|
}
|
|
5204
5204
|
};
|
|
5205
5205
|
}
|
|
5206
|
-
const
|
|
5207
|
-
const
|
|
5208
|
-
const fullPath =
|
|
5206
|
+
const fs50 = await import("node:fs/promises");
|
|
5207
|
+
const path59 = await import("node:path");
|
|
5208
|
+
const fullPath = path59.isAbsolute(filePath) ? filePath : path59.join(projectPath, filePath);
|
|
5209
5209
|
try {
|
|
5210
|
-
const stat = await
|
|
5210
|
+
const stat = await fs50.stat(fullPath);
|
|
5211
5211
|
if (stat.isDirectory()) {
|
|
5212
5212
|
const results = await extractDirectorySignatures(filePath, projectPath, {
|
|
5213
5213
|
recursive: args2.includes("--recursive") || args2.includes("-r")
|
|
@@ -5274,11 +5274,11 @@ async function runSummaryTool(args2, projectPath) {
|
|
|
5274
5274
|
}
|
|
5275
5275
|
};
|
|
5276
5276
|
}
|
|
5277
|
-
const
|
|
5278
|
-
const
|
|
5279
|
-
const fullPath =
|
|
5277
|
+
const fs50 = await import("node:fs/promises");
|
|
5278
|
+
const path59 = await import("node:path");
|
|
5279
|
+
const fullPath = path59.isAbsolute(targetPath) ? targetPath : path59.join(projectPath, targetPath);
|
|
5280
5280
|
try {
|
|
5281
|
-
const stat = await
|
|
5281
|
+
const stat = await fs50.stat(fullPath);
|
|
5282
5282
|
if (stat.isDirectory()) {
|
|
5283
5283
|
const results = await summarizeDirectory(targetPath, projectPath, {
|
|
5284
5284
|
recursive: args2.includes("--recursive") || args2.includes("-r")
|
|
@@ -15594,6 +15594,249 @@ var init_file_scorer = __esm({
|
|
|
15594
15594
|
}
|
|
15595
15595
|
});
|
|
15596
15596
|
|
|
15597
|
+
// core/services/dependency-validator.ts
|
|
15598
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
15599
|
+
var TOOLS, DependencyValidator, DependencyError, dependencyValidator;
|
|
15600
|
+
var init_dependency_validator = __esm({
|
|
15601
|
+
"core/services/dependency-validator.ts"() {
|
|
15602
|
+
"use strict";
|
|
15603
|
+
init_error_messages();
|
|
15604
|
+
TOOLS = {
|
|
15605
|
+
git: {
|
|
15606
|
+
name: "git",
|
|
15607
|
+
command: "git --version",
|
|
15608
|
+
versionRegex: /git version ([\d.]+)/,
|
|
15609
|
+
required: true,
|
|
15610
|
+
installHint: "Install Git: https://git-scm.com/downloads",
|
|
15611
|
+
docs: "https://git-scm.com/doc"
|
|
15612
|
+
},
|
|
15613
|
+
node: {
|
|
15614
|
+
name: "node",
|
|
15615
|
+
command: "node --version",
|
|
15616
|
+
versionRegex: /v([\d.]+)/,
|
|
15617
|
+
required: true,
|
|
15618
|
+
installHint: "Install Node.js: https://nodejs.org",
|
|
15619
|
+
docs: "https://nodejs.org/docs"
|
|
15620
|
+
},
|
|
15621
|
+
bun: {
|
|
15622
|
+
name: "bun",
|
|
15623
|
+
command: "bun --version",
|
|
15624
|
+
versionRegex: /([\d.]+)/,
|
|
15625
|
+
required: false,
|
|
15626
|
+
installHint: "Install Bun: curl -fsSL https://bun.sh/install | bash",
|
|
15627
|
+
docs: "https://bun.sh/docs"
|
|
15628
|
+
},
|
|
15629
|
+
gh: {
|
|
15630
|
+
name: "gh",
|
|
15631
|
+
command: "gh --version",
|
|
15632
|
+
versionRegex: /gh version ([\d.]+)/,
|
|
15633
|
+
required: false,
|
|
15634
|
+
installHint: "Install GitHub CLI: https://cli.github.com",
|
|
15635
|
+
docs: "https://cli.github.com/manual"
|
|
15636
|
+
},
|
|
15637
|
+
npm: {
|
|
15638
|
+
name: "npm",
|
|
15639
|
+
command: "npm --version",
|
|
15640
|
+
versionRegex: /([\d.]+)/,
|
|
15641
|
+
required: false,
|
|
15642
|
+
installHint: "npm comes with Node.js: https://nodejs.org"
|
|
15643
|
+
},
|
|
15644
|
+
claude: {
|
|
15645
|
+
name: "claude",
|
|
15646
|
+
command: "claude --version",
|
|
15647
|
+
versionRegex: /claude ([\d.]+)/,
|
|
15648
|
+
required: false,
|
|
15649
|
+
installHint: "Install Claude Code: npm install -g @anthropic-ai/claude-code",
|
|
15650
|
+
docs: "https://docs.anthropic.com/claude-code"
|
|
15651
|
+
},
|
|
15652
|
+
gemini: {
|
|
15653
|
+
name: "gemini",
|
|
15654
|
+
command: "gemini --version",
|
|
15655
|
+
versionRegex: /gemini ([\d.]+)/,
|
|
15656
|
+
required: false,
|
|
15657
|
+
installHint: "Install Gemini CLI: npm install -g @google/gemini-cli",
|
|
15658
|
+
docs: "https://ai.google.dev/gemini-api/docs"
|
|
15659
|
+
}
|
|
15660
|
+
};
|
|
15661
|
+
DependencyValidator = class {
|
|
15662
|
+
static {
|
|
15663
|
+
__name(this, "DependencyValidator");
|
|
15664
|
+
}
|
|
15665
|
+
cache = /* @__PURE__ */ new Map();
|
|
15666
|
+
cacheTimeout = 6e4;
|
|
15667
|
+
// 1 minute cache
|
|
15668
|
+
cacheTimestamps = /* @__PURE__ */ new Map();
|
|
15669
|
+
/**
|
|
15670
|
+
* Check if a tool is available
|
|
15671
|
+
* Uses caching to avoid repeated execSync calls
|
|
15672
|
+
*/
|
|
15673
|
+
checkTool(toolName) {
|
|
15674
|
+
const cached = this.getCached(toolName);
|
|
15675
|
+
if (cached) return cached;
|
|
15676
|
+
const definition = TOOLS[toolName];
|
|
15677
|
+
if (!definition) {
|
|
15678
|
+
return this.checkUnknownTool(toolName);
|
|
15679
|
+
}
|
|
15680
|
+
const status = this.executeCheck(definition);
|
|
15681
|
+
this.setCache(toolName, status);
|
|
15682
|
+
return status;
|
|
15683
|
+
}
|
|
15684
|
+
/**
|
|
15685
|
+
* Ensure a tool is available, throw helpful error if not
|
|
15686
|
+
* Use this before operations that require a specific tool
|
|
15687
|
+
*/
|
|
15688
|
+
ensureTool(toolName) {
|
|
15689
|
+
const status = this.checkTool(toolName);
|
|
15690
|
+
if (!status.available) {
|
|
15691
|
+
const definition = TOOLS[toolName];
|
|
15692
|
+
const error = status.error || {
|
|
15693
|
+
message: `${toolName} is not available`,
|
|
15694
|
+
hint: definition?.installHint || `Install ${toolName} and try again`,
|
|
15695
|
+
docs: definition?.docs
|
|
15696
|
+
};
|
|
15697
|
+
throw new DependencyError(error);
|
|
15698
|
+
}
|
|
15699
|
+
}
|
|
15700
|
+
/**
|
|
15701
|
+
* Ensure multiple tools are available
|
|
15702
|
+
*/
|
|
15703
|
+
ensureTools(toolNames) {
|
|
15704
|
+
const missing = [];
|
|
15705
|
+
for (const name of toolNames) {
|
|
15706
|
+
const status = this.checkTool(name);
|
|
15707
|
+
if (!status.available) {
|
|
15708
|
+
missing.push(name);
|
|
15709
|
+
}
|
|
15710
|
+
}
|
|
15711
|
+
if (missing.length > 0) {
|
|
15712
|
+
const hints = missing.map((name) => {
|
|
15713
|
+
const def = TOOLS[name];
|
|
15714
|
+
return def ? ` ${name}: ${def.installHint}` : ` ${name}: Install and try again`;
|
|
15715
|
+
}).join("\n");
|
|
15716
|
+
throw new DependencyError({
|
|
15717
|
+
message: `Missing required tools: ${missing.join(", ")}`,
|
|
15718
|
+
hint: `Install the following:
|
|
15719
|
+
${hints}`
|
|
15720
|
+
});
|
|
15721
|
+
}
|
|
15722
|
+
}
|
|
15723
|
+
/**
|
|
15724
|
+
* Check if tool is available (boolean convenience method)
|
|
15725
|
+
*/
|
|
15726
|
+
isAvailable(toolName) {
|
|
15727
|
+
return this.checkTool(toolName).available;
|
|
15728
|
+
}
|
|
15729
|
+
/**
|
|
15730
|
+
* Get tool version if available
|
|
15731
|
+
*/
|
|
15732
|
+
getVersion(toolName) {
|
|
15733
|
+
return this.checkTool(toolName).version;
|
|
15734
|
+
}
|
|
15735
|
+
/**
|
|
15736
|
+
* Check multiple tools and return summary
|
|
15737
|
+
*/
|
|
15738
|
+
checkAll(toolNames) {
|
|
15739
|
+
const names = toolNames || Object.keys(TOOLS);
|
|
15740
|
+
const results = /* @__PURE__ */ new Map();
|
|
15741
|
+
for (const name of names) {
|
|
15742
|
+
results.set(name, this.checkTool(name));
|
|
15743
|
+
}
|
|
15744
|
+
return results;
|
|
15745
|
+
}
|
|
15746
|
+
/**
|
|
15747
|
+
* Clear the cache (useful for tests or after installations)
|
|
15748
|
+
*/
|
|
15749
|
+
clearCache() {
|
|
15750
|
+
this.cache.clear();
|
|
15751
|
+
this.cacheTimestamps.clear();
|
|
15752
|
+
}
|
|
15753
|
+
// ==========================================================================
|
|
15754
|
+
// PRIVATE METHODS
|
|
15755
|
+
// ==========================================================================
|
|
15756
|
+
executeCheck(definition) {
|
|
15757
|
+
try {
|
|
15758
|
+
const output = execSync4(definition.command, {
|
|
15759
|
+
encoding: "utf-8",
|
|
15760
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
15761
|
+
timeout: 5e3
|
|
15762
|
+
// 5 second timeout
|
|
15763
|
+
});
|
|
15764
|
+
let version;
|
|
15765
|
+
if (definition.versionRegex) {
|
|
15766
|
+
const match = output.match(definition.versionRegex);
|
|
15767
|
+
version = match ? match[1] : void 0;
|
|
15768
|
+
}
|
|
15769
|
+
return { available: true, version };
|
|
15770
|
+
} catch {
|
|
15771
|
+
return {
|
|
15772
|
+
available: false,
|
|
15773
|
+
error: createError(
|
|
15774
|
+
`${definition.name} is not installed or not in PATH`,
|
|
15775
|
+
definition.installHint,
|
|
15776
|
+
{ docs: definition.docs }
|
|
15777
|
+
)
|
|
15778
|
+
};
|
|
15779
|
+
}
|
|
15780
|
+
}
|
|
15781
|
+
checkUnknownTool(toolName) {
|
|
15782
|
+
try {
|
|
15783
|
+
execSync4(`${toolName} --version`, {
|
|
15784
|
+
encoding: "utf-8",
|
|
15785
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
15786
|
+
timeout: 5e3
|
|
15787
|
+
});
|
|
15788
|
+
return { available: true };
|
|
15789
|
+
} catch {
|
|
15790
|
+
try {
|
|
15791
|
+
execSync4(`${toolName} -v`, {
|
|
15792
|
+
encoding: "utf-8",
|
|
15793
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
15794
|
+
timeout: 5e3
|
|
15795
|
+
});
|
|
15796
|
+
return { available: true };
|
|
15797
|
+
} catch {
|
|
15798
|
+
return {
|
|
15799
|
+
available: false,
|
|
15800
|
+
error: createError(
|
|
15801
|
+
`${toolName} is not installed or not in PATH`,
|
|
15802
|
+
`Install ${toolName} and try again`
|
|
15803
|
+
)
|
|
15804
|
+
};
|
|
15805
|
+
}
|
|
15806
|
+
}
|
|
15807
|
+
}
|
|
15808
|
+
getCached(toolName) {
|
|
15809
|
+
const timestamp = this.cacheTimestamps.get(toolName);
|
|
15810
|
+
if (!timestamp) return null;
|
|
15811
|
+
if (Date.now() - timestamp > this.cacheTimeout) {
|
|
15812
|
+
this.cache.delete(toolName);
|
|
15813
|
+
this.cacheTimestamps.delete(toolName);
|
|
15814
|
+
return null;
|
|
15815
|
+
}
|
|
15816
|
+
return this.cache.get(toolName) || null;
|
|
15817
|
+
}
|
|
15818
|
+
setCache(toolName, status) {
|
|
15819
|
+
this.cache.set(toolName, status);
|
|
15820
|
+
this.cacheTimestamps.set(toolName, Date.now());
|
|
15821
|
+
}
|
|
15822
|
+
};
|
|
15823
|
+
DependencyError = class extends Error {
|
|
15824
|
+
static {
|
|
15825
|
+
__name(this, "DependencyError");
|
|
15826
|
+
}
|
|
15827
|
+
hint;
|
|
15828
|
+
docs;
|
|
15829
|
+
constructor(error) {
|
|
15830
|
+
super(error.message);
|
|
15831
|
+
this.name = "DependencyError";
|
|
15832
|
+
this.hint = error.hint;
|
|
15833
|
+
this.docs = error.docs;
|
|
15834
|
+
}
|
|
15835
|
+
};
|
|
15836
|
+
dependencyValidator = new DependencyValidator();
|
|
15837
|
+
}
|
|
15838
|
+
});
|
|
15839
|
+
|
|
15597
15840
|
// core/services/git-analyzer.ts
|
|
15598
15841
|
import { exec as exec6 } from "node:child_process";
|
|
15599
15842
|
import { promisify as promisify6 } from "node:util";
|
|
@@ -15601,6 +15844,7 @@ var execAsync2;
|
|
|
15601
15844
|
var init_git_analyzer = __esm({
|
|
15602
15845
|
"core/services/git-analyzer.ts"() {
|
|
15603
15846
|
"use strict";
|
|
15847
|
+
init_dependency_validator();
|
|
15604
15848
|
execAsync2 = promisify6(exec6);
|
|
15605
15849
|
}
|
|
15606
15850
|
});
|
|
@@ -16758,16 +17002,16 @@ var init_onboarding = __esm({
|
|
|
16758
17002
|
* Detect project type from file system
|
|
16759
17003
|
*/
|
|
16760
17004
|
async detectProjectType() {
|
|
16761
|
-
const
|
|
16762
|
-
const
|
|
17005
|
+
const fs50 = await import("node:fs/promises");
|
|
17006
|
+
const path59 = await import("node:path");
|
|
16763
17007
|
try {
|
|
16764
|
-
const files = await
|
|
17008
|
+
const files = await fs50.readdir(this.projectPath);
|
|
16765
17009
|
if (files.includes("turbo.json") || files.includes("lerna.json") || files.includes("nx.json")) {
|
|
16766
17010
|
return "monorepo";
|
|
16767
17011
|
}
|
|
16768
17012
|
if (files.includes("package.json")) {
|
|
16769
|
-
const pkgPath =
|
|
16770
|
-
const pkgContent = await
|
|
17013
|
+
const pkgPath = path59.join(this.projectPath, "package.json");
|
|
17014
|
+
const pkgContent = await fs50.readFile(pkgPath, "utf-8");
|
|
16771
17015
|
const pkg = JSON.parse(pkgContent);
|
|
16772
17016
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
16773
17017
|
if (pkg.bin) return "cli-tool";
|
|
@@ -16803,32 +17047,32 @@ var init_onboarding = __esm({
|
|
|
16803
17047
|
* Detect installed AI agents from config files
|
|
16804
17048
|
*/
|
|
16805
17049
|
async detectInstalledAgents() {
|
|
16806
|
-
const
|
|
16807
|
-
const
|
|
17050
|
+
const fs50 = await import("node:fs/promises");
|
|
17051
|
+
const path59 = await import("node:path");
|
|
16808
17052
|
const os17 = await import("node:os");
|
|
16809
17053
|
const agents = [];
|
|
16810
17054
|
try {
|
|
16811
|
-
await
|
|
17055
|
+
await fs50.access(path59.join(os17.homedir(), ".claude"));
|
|
16812
17056
|
agents.push("claude");
|
|
16813
17057
|
} catch {
|
|
16814
17058
|
}
|
|
16815
17059
|
try {
|
|
16816
|
-
await
|
|
17060
|
+
await fs50.access(path59.join(this.projectPath, ".cursorrules"));
|
|
16817
17061
|
agents.push("cursor");
|
|
16818
17062
|
} catch {
|
|
16819
17063
|
}
|
|
16820
17064
|
try {
|
|
16821
|
-
await
|
|
17065
|
+
await fs50.access(path59.join(this.projectPath, ".windsurfrules"));
|
|
16822
17066
|
agents.push("windsurf");
|
|
16823
17067
|
} catch {
|
|
16824
17068
|
}
|
|
16825
17069
|
try {
|
|
16826
|
-
await
|
|
17070
|
+
await fs50.access(path59.join(this.projectPath, ".github", "copilot-instructions.md"));
|
|
16827
17071
|
agents.push("copilot");
|
|
16828
17072
|
} catch {
|
|
16829
17073
|
}
|
|
16830
17074
|
try {
|
|
16831
|
-
await
|
|
17075
|
+
await fs50.access(path59.join(os17.homedir(), ".gemini"));
|
|
16832
17076
|
agents.push("gemini");
|
|
16833
17077
|
} catch {
|
|
16834
17078
|
}
|
|
@@ -16838,17 +17082,17 @@ var init_onboarding = __esm({
|
|
|
16838
17082
|
* Detect tech stack from project files
|
|
16839
17083
|
*/
|
|
16840
17084
|
async detectStack() {
|
|
16841
|
-
const
|
|
16842
|
-
const
|
|
17085
|
+
const fs50 = await import("node:fs/promises");
|
|
17086
|
+
const path59 = await import("node:path");
|
|
16843
17087
|
const stack = {
|
|
16844
17088
|
language: "Unknown",
|
|
16845
17089
|
technologies: []
|
|
16846
17090
|
};
|
|
16847
17091
|
try {
|
|
16848
|
-
const files = await
|
|
17092
|
+
const files = await fs50.readdir(this.projectPath);
|
|
16849
17093
|
if (files.includes("package.json")) {
|
|
16850
|
-
const pkgPath =
|
|
16851
|
-
const pkgContent = await
|
|
17094
|
+
const pkgPath = path59.join(this.projectPath, "package.json");
|
|
17095
|
+
const pkgContent = await fs50.readFile(pkgPath, "utf-8");
|
|
16852
17096
|
const pkg = JSON.parse(pkgContent);
|
|
16853
17097
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
16854
17098
|
stack.language = deps.typescript ? "TypeScript" : "JavaScript";
|
|
@@ -18944,8 +19188,8 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
|
18944
19188
|
const globalPath2 = path_manager_default.getGlobalProjectPath(projectId);
|
|
18945
19189
|
const specsPath2 = path37.join(globalPath2, "planning", "specs");
|
|
18946
19190
|
try {
|
|
18947
|
-
const
|
|
18948
|
-
const files = await
|
|
19191
|
+
const fs50 = await import("node:fs/promises");
|
|
19192
|
+
const files = await fs50.readdir(specsPath2);
|
|
18949
19193
|
const specs = files.filter((f) => f.endsWith(".md") && f !== ".gitkeep");
|
|
18950
19194
|
if (specs.length === 0) {
|
|
18951
19195
|
output_default.warn("no specs yet");
|
|
@@ -19567,7 +19811,7 @@ var init_formatters = __esm({
|
|
|
19567
19811
|
});
|
|
19568
19812
|
|
|
19569
19813
|
// core/ai-tools/registry.ts
|
|
19570
|
-
import { execSync as
|
|
19814
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
19571
19815
|
import fs37 from "node:fs";
|
|
19572
19816
|
import os11 from "node:os";
|
|
19573
19817
|
import path39 from "node:path";
|
|
@@ -19576,7 +19820,7 @@ function getAIToolConfig(id) {
|
|
|
19576
19820
|
}
|
|
19577
19821
|
function commandExists(cmd) {
|
|
19578
19822
|
try {
|
|
19579
|
-
|
|
19823
|
+
execSync5(`which ${cmd}`, { stdio: "ignore" });
|
|
19580
19824
|
return true;
|
|
19581
19825
|
} catch {
|
|
19582
19826
|
return false;
|
|
@@ -20088,9 +20332,125 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
|
|
|
20088
20332
|
}
|
|
20089
20333
|
});
|
|
20090
20334
|
|
|
20091
|
-
// core/services/
|
|
20335
|
+
// core/services/local-state-generator.ts
|
|
20092
20336
|
import fs40 from "node:fs/promises";
|
|
20093
20337
|
import path42 from "node:path";
|
|
20338
|
+
var LOCAL_STATE_FILENAME, LocalStateGenerator, localStateGenerator;
|
|
20339
|
+
var init_local_state_generator = __esm({
|
|
20340
|
+
"core/services/local-state-generator.ts"() {
|
|
20341
|
+
"use strict";
|
|
20342
|
+
init_fs();
|
|
20343
|
+
LOCAL_STATE_FILENAME = ".prjct-state.md";
|
|
20344
|
+
LocalStateGenerator = class {
|
|
20345
|
+
static {
|
|
20346
|
+
__name(this, "LocalStateGenerator");
|
|
20347
|
+
}
|
|
20348
|
+
/**
|
|
20349
|
+
* Generate .prjct-state.md in the project root
|
|
20350
|
+
*/
|
|
20351
|
+
async generate(projectPath, state) {
|
|
20352
|
+
const filePath = path42.join(projectPath, LOCAL_STATE_FILENAME);
|
|
20353
|
+
const content = this.toMarkdown(state);
|
|
20354
|
+
await fs40.writeFile(filePath, content, "utf-8");
|
|
20355
|
+
}
|
|
20356
|
+
/**
|
|
20357
|
+
* Remove local state file
|
|
20358
|
+
*/
|
|
20359
|
+
async remove(projectPath) {
|
|
20360
|
+
const filePath = path42.join(projectPath, LOCAL_STATE_FILENAME);
|
|
20361
|
+
try {
|
|
20362
|
+
await fs40.unlink(filePath);
|
|
20363
|
+
} catch (error) {
|
|
20364
|
+
if (!isNotFoundError(error)) throw error;
|
|
20365
|
+
}
|
|
20366
|
+
}
|
|
20367
|
+
/**
|
|
20368
|
+
* Check if local state file exists
|
|
20369
|
+
*/
|
|
20370
|
+
async exists(projectPath) {
|
|
20371
|
+
const filePath = path42.join(projectPath, LOCAL_STATE_FILENAME);
|
|
20372
|
+
try {
|
|
20373
|
+
await fs40.access(filePath);
|
|
20374
|
+
return true;
|
|
20375
|
+
} catch {
|
|
20376
|
+
return false;
|
|
20377
|
+
}
|
|
20378
|
+
}
|
|
20379
|
+
/**
|
|
20380
|
+
* Convert state to markdown format
|
|
20381
|
+
* Note: Uses runtime types since state.json has fields not in strict Zod schema
|
|
20382
|
+
*/
|
|
20383
|
+
toMarkdown(state) {
|
|
20384
|
+
const lines = [
|
|
20385
|
+
"<!-- Auto-generated by prjct - DO NOT EDIT -->",
|
|
20386
|
+
"<!-- This file provides local state persistence for AI tools -->",
|
|
20387
|
+
"",
|
|
20388
|
+
"# prjct State",
|
|
20389
|
+
""
|
|
20390
|
+
];
|
|
20391
|
+
if (state.currentTask) {
|
|
20392
|
+
const task = state.currentTask;
|
|
20393
|
+
lines.push("## Current Task");
|
|
20394
|
+
lines.push("");
|
|
20395
|
+
lines.push(`**${task.description}**`);
|
|
20396
|
+
lines.push("");
|
|
20397
|
+
lines.push(`- Started: ${task.startedAt}`);
|
|
20398
|
+
if (task.linearId) {
|
|
20399
|
+
lines.push(`- Linear: ${task.linearId}`);
|
|
20400
|
+
}
|
|
20401
|
+
if (task.branch) {
|
|
20402
|
+
lines.push(`- Branch: ${task.branch}`);
|
|
20403
|
+
}
|
|
20404
|
+
lines.push(`- Status: ${task.status || "active"}`);
|
|
20405
|
+
lines.push("");
|
|
20406
|
+
if (task.subtasks && task.subtasks.length > 0) {
|
|
20407
|
+
lines.push("### Subtasks");
|
|
20408
|
+
lines.push("");
|
|
20409
|
+
task.subtasks.forEach((subtask, index) => {
|
|
20410
|
+
const statusIcon = subtask.status === "completed" ? "\u2705" : subtask.status === "in_progress" ? "\u25B6\uFE0F" : "\u23F3";
|
|
20411
|
+
const isActive = index === task.currentSubtaskIndex ? " \u2190 **Active**" : "";
|
|
20412
|
+
lines.push(`${index + 1}. ${statusIcon} ${subtask.description}${isActive}`);
|
|
20413
|
+
});
|
|
20414
|
+
lines.push("");
|
|
20415
|
+
const completed = task.subtasks.filter((s) => s.status === "completed").length;
|
|
20416
|
+
const total = task.subtasks.length;
|
|
20417
|
+
const percentage = Math.round(completed / total * 100);
|
|
20418
|
+
lines.push(`**Progress**: ${completed}/${total} (${percentage}%)`);
|
|
20419
|
+
lines.push("");
|
|
20420
|
+
}
|
|
20421
|
+
} else {
|
|
20422
|
+
lines.push("*No active task*");
|
|
20423
|
+
lines.push("");
|
|
20424
|
+
lines.push('Start a task with `p. task "description"`');
|
|
20425
|
+
lines.push("");
|
|
20426
|
+
}
|
|
20427
|
+
if (state.previousTask) {
|
|
20428
|
+
const prevTask = state.previousTask;
|
|
20429
|
+
lines.push("---");
|
|
20430
|
+
lines.push("");
|
|
20431
|
+
lines.push("## Previous Task");
|
|
20432
|
+
lines.push("");
|
|
20433
|
+
lines.push(`**${prevTask.description}**`);
|
|
20434
|
+
lines.push("");
|
|
20435
|
+
lines.push(`- Status: ${prevTask.status}`);
|
|
20436
|
+
if (prevTask.prUrl) {
|
|
20437
|
+
lines.push(`- PR: ${prevTask.prUrl}`);
|
|
20438
|
+
}
|
|
20439
|
+
lines.push("");
|
|
20440
|
+
}
|
|
20441
|
+
lines.push("---");
|
|
20442
|
+
lines.push(`*Last updated: ${state.lastUpdated || (/* @__PURE__ */ new Date()).toISOString()}*`);
|
|
20443
|
+
lines.push("");
|
|
20444
|
+
return lines.join("\n");
|
|
20445
|
+
}
|
|
20446
|
+
};
|
|
20447
|
+
localStateGenerator = new LocalStateGenerator();
|
|
20448
|
+
}
|
|
20449
|
+
});
|
|
20450
|
+
|
|
20451
|
+
// core/services/stack-detector.ts
|
|
20452
|
+
import fs41 from "node:fs/promises";
|
|
20453
|
+
import path43 from "node:path";
|
|
20094
20454
|
var StackDetector;
|
|
20095
20455
|
var init_stack_detector = __esm({
|
|
20096
20456
|
"core/services/stack-detector.ts"() {
|
|
@@ -20249,8 +20609,8 @@ var init_stack_detector = __esm({
|
|
|
20249
20609
|
*/
|
|
20250
20610
|
async readPackageJson() {
|
|
20251
20611
|
try {
|
|
20252
|
-
const pkgPath =
|
|
20253
|
-
const content = await
|
|
20612
|
+
const pkgPath = path43.join(this.projectPath, "package.json");
|
|
20613
|
+
const content = await fs41.readFile(pkgPath, "utf-8");
|
|
20254
20614
|
return JSON.parse(content);
|
|
20255
20615
|
} catch {
|
|
20256
20616
|
return null;
|
|
@@ -20261,7 +20621,7 @@ var init_stack_detector = __esm({
|
|
|
20261
20621
|
*/
|
|
20262
20622
|
async fileExists(filename) {
|
|
20263
20623
|
try {
|
|
20264
|
-
await
|
|
20624
|
+
await fs41.access(path43.join(this.projectPath, filename));
|
|
20265
20625
|
return true;
|
|
20266
20626
|
} catch {
|
|
20267
20627
|
return false;
|
|
@@ -20273,8 +20633,8 @@ var init_stack_detector = __esm({
|
|
|
20273
20633
|
|
|
20274
20634
|
// core/services/sync-service.ts
|
|
20275
20635
|
import { exec as exec11 } from "node:child_process";
|
|
20276
|
-
import
|
|
20277
|
-
import
|
|
20636
|
+
import fs42 from "node:fs/promises";
|
|
20637
|
+
import path44 from "node:path";
|
|
20278
20638
|
import { promisify as promisify11 } from "node:util";
|
|
20279
20639
|
var execAsync6, SyncService, syncService;
|
|
20280
20640
|
var init_sync_service = __esm({
|
|
@@ -20287,6 +20647,7 @@ var init_sync_service = __esm({
|
|
|
20287
20647
|
init_metrics_storage();
|
|
20288
20648
|
init_date_helper();
|
|
20289
20649
|
init_context_generator();
|
|
20650
|
+
init_local_state_generator();
|
|
20290
20651
|
init_stack_detector();
|
|
20291
20652
|
execAsync6 = promisify11(exec11);
|
|
20292
20653
|
SyncService = class {
|
|
@@ -20423,7 +20784,7 @@ var init_sync_service = __esm({
|
|
|
20423
20784
|
async ensureDirectories() {
|
|
20424
20785
|
const dirs = ["storage", "context", "agents", "memory", "analysis", "config", "sync"];
|
|
20425
20786
|
await Promise.all(
|
|
20426
|
-
dirs.map((dir) =>
|
|
20787
|
+
dirs.map((dir) => fs42.mkdir(path44.join(this.globalPath, dir), { recursive: true }))
|
|
20427
20788
|
);
|
|
20428
20789
|
}
|
|
20429
20790
|
// ==========================================================================
|
|
@@ -20493,7 +20854,7 @@ var init_sync_service = __esm({
|
|
|
20493
20854
|
const stats = {
|
|
20494
20855
|
fileCount: 0,
|
|
20495
20856
|
version: "0.0.0",
|
|
20496
|
-
name:
|
|
20857
|
+
name: path44.basename(this.projectPath),
|
|
20497
20858
|
ecosystem: "unknown",
|
|
20498
20859
|
projectType: "simple",
|
|
20499
20860
|
languages: [],
|
|
@@ -20509,8 +20870,8 @@ var init_sync_service = __esm({
|
|
|
20509
20870
|
stats.fileCount = 0;
|
|
20510
20871
|
}
|
|
20511
20872
|
try {
|
|
20512
|
-
const pkgPath =
|
|
20513
|
-
const pkg = JSON.parse(await
|
|
20873
|
+
const pkgPath = path44.join(this.projectPath, "package.json");
|
|
20874
|
+
const pkg = JSON.parse(await fs42.readFile(pkgPath, "utf-8"));
|
|
20514
20875
|
stats.version = pkg.version || "0.0.0";
|
|
20515
20876
|
stats.name = pkg.name || stats.name;
|
|
20516
20877
|
stats.ecosystem = "JavaScript";
|
|
@@ -20618,12 +20979,12 @@ var init_sync_service = __esm({
|
|
|
20618
20979
|
// ==========================================================================
|
|
20619
20980
|
async generateAgents(stack, stats) {
|
|
20620
20981
|
const agents = [];
|
|
20621
|
-
const agentsPath =
|
|
20982
|
+
const agentsPath = path44.join(this.globalPath, "agents");
|
|
20622
20983
|
try {
|
|
20623
|
-
const files = await
|
|
20984
|
+
const files = await fs42.readdir(agentsPath);
|
|
20624
20985
|
for (const file of files) {
|
|
20625
20986
|
if (file.endsWith(".md")) {
|
|
20626
|
-
await
|
|
20987
|
+
await fs42.unlink(path44.join(agentsPath, file));
|
|
20627
20988
|
}
|
|
20628
20989
|
}
|
|
20629
20990
|
} catch {
|
|
@@ -20663,7 +21024,7 @@ var init_sync_service = __esm({
|
|
|
20663
21024
|
async generateWorkflowAgent(name, agentsPath) {
|
|
20664
21025
|
let content = "";
|
|
20665
21026
|
try {
|
|
20666
|
-
const templatePath =
|
|
21027
|
+
const templatePath = path44.join(
|
|
20667
21028
|
__dirname,
|
|
20668
21029
|
"..",
|
|
20669
21030
|
"..",
|
|
@@ -20672,16 +21033,16 @@ var init_sync_service = __esm({
|
|
|
20672
21033
|
"workflow",
|
|
20673
21034
|
`${name}.md`
|
|
20674
21035
|
);
|
|
20675
|
-
content = await
|
|
21036
|
+
content = await fs42.readFile(templatePath, "utf-8");
|
|
20676
21037
|
} catch {
|
|
20677
21038
|
content = this.generateMinimalWorkflowAgent(name);
|
|
20678
21039
|
}
|
|
20679
|
-
await
|
|
21040
|
+
await fs42.writeFile(path44.join(agentsPath, `${name}.md`), content, "utf-8");
|
|
20680
21041
|
}
|
|
20681
21042
|
async generateDomainAgent(name, agentsPath, stats, stack) {
|
|
20682
21043
|
let content = "";
|
|
20683
21044
|
try {
|
|
20684
|
-
const templatePath =
|
|
21045
|
+
const templatePath = path44.join(
|
|
20685
21046
|
__dirname,
|
|
20686
21047
|
"..",
|
|
20687
21048
|
"..",
|
|
@@ -20690,14 +21051,14 @@ var init_sync_service = __esm({
|
|
|
20690
21051
|
"domain",
|
|
20691
21052
|
`${name}.md`
|
|
20692
21053
|
);
|
|
20693
|
-
content = await
|
|
21054
|
+
content = await fs42.readFile(templatePath, "utf-8");
|
|
20694
21055
|
content = content.replace("{projectName}", stats.name);
|
|
20695
21056
|
content = content.replace("{frameworks}", stack.frameworks.join(", ") || "None detected");
|
|
20696
21057
|
content = content.replace("{ecosystem}", stats.ecosystem);
|
|
20697
21058
|
} catch {
|
|
20698
21059
|
content = this.generateMinimalDomainAgent(name, stats, stack);
|
|
20699
21060
|
}
|
|
20700
|
-
await
|
|
21061
|
+
await fs42.writeFile(path44.join(agentsPath, `${name}.md`), content, "utf-8");
|
|
20701
21062
|
}
|
|
20702
21063
|
generateMinimalWorkflowAgent(name) {
|
|
20703
21064
|
const descriptions = {
|
|
@@ -20765,8 +21126,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
20765
21126
|
})),
|
|
20766
21127
|
agentSkillMap: Object.fromEntries(skills.map((s) => [s.agent, s.skill]))
|
|
20767
21128
|
};
|
|
20768
|
-
|
|
20769
|
-
|
|
21129
|
+
fs42.writeFile(
|
|
21130
|
+
path44.join(this.globalPath, "config", "skills.json"),
|
|
20770
21131
|
JSON.stringify(skillsConfig, null, 2),
|
|
20771
21132
|
"utf-8"
|
|
20772
21133
|
).catch(() => {
|
|
@@ -20788,10 +21149,10 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
20788
21149
|
// PROJECT.JSON UPDATE
|
|
20789
21150
|
// ==========================================================================
|
|
20790
21151
|
async updateProjectJson(git, stats) {
|
|
20791
|
-
const projectJsonPath =
|
|
21152
|
+
const projectJsonPath = path44.join(this.globalPath, "project.json");
|
|
20792
21153
|
let existing = {};
|
|
20793
21154
|
try {
|
|
20794
|
-
existing = JSON.parse(await
|
|
21155
|
+
existing = JSON.parse(await fs42.readFile(projectJsonPath, "utf-8"));
|
|
20795
21156
|
} catch {
|
|
20796
21157
|
}
|
|
20797
21158
|
const updated = {
|
|
@@ -20813,16 +21174,16 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
20813
21174
|
lastSyncCommit: git.recentCommits[0]?.hash || null,
|
|
20814
21175
|
lastSyncBranch: git.branch
|
|
20815
21176
|
};
|
|
20816
|
-
await
|
|
21177
|
+
await fs42.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
20817
21178
|
}
|
|
20818
21179
|
// ==========================================================================
|
|
20819
21180
|
// STATE.JSON UPDATE
|
|
20820
21181
|
// ==========================================================================
|
|
20821
21182
|
async updateStateJson(stats, stack) {
|
|
20822
|
-
const statePath =
|
|
21183
|
+
const statePath = path44.join(this.globalPath, "storage", "state.json");
|
|
20823
21184
|
let state = {};
|
|
20824
21185
|
try {
|
|
20825
|
-
state = JSON.parse(await
|
|
21186
|
+
state = JSON.parse(await fs42.readFile(statePath, "utf-8"));
|
|
20826
21187
|
} catch {
|
|
20827
21188
|
}
|
|
20828
21189
|
state.projectId = this.projectId;
|
|
@@ -20849,13 +21210,20 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
20849
21210
|
lastAction: "Synced project",
|
|
20850
21211
|
nextAction: 'Run `p. task "description"` to start working'
|
|
20851
21212
|
};
|
|
20852
|
-
await
|
|
21213
|
+
await fs42.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
|
|
21214
|
+
try {
|
|
21215
|
+
await localStateGenerator.generate(
|
|
21216
|
+
this.projectPath,
|
|
21217
|
+
state
|
|
21218
|
+
);
|
|
21219
|
+
} catch {
|
|
21220
|
+
}
|
|
20853
21221
|
}
|
|
20854
21222
|
// ==========================================================================
|
|
20855
21223
|
// MEMORY LOGGING
|
|
20856
21224
|
// ==========================================================================
|
|
20857
21225
|
async logToMemory(git, stats) {
|
|
20858
|
-
const memoryPath =
|
|
21226
|
+
const memoryPath = path44.join(this.globalPath, "memory", "events.jsonl");
|
|
20859
21227
|
const event = {
|
|
20860
21228
|
ts: date_helper_default.getTimestamp(),
|
|
20861
21229
|
action: "sync",
|
|
@@ -20864,7 +21232,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
20864
21232
|
fileCount: stats.fileCount,
|
|
20865
21233
|
commitCount: git.commits
|
|
20866
21234
|
};
|
|
20867
|
-
await
|
|
21235
|
+
await fs42.appendFile(memoryPath, `${JSON.stringify(event)}
|
|
20868
21236
|
`, "utf-8");
|
|
20869
21237
|
}
|
|
20870
21238
|
// ==========================================================================
|
|
@@ -20884,16 +21252,16 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
20884
21252
|
let filteredChars = 0;
|
|
20885
21253
|
for (const file of contextFiles) {
|
|
20886
21254
|
try {
|
|
20887
|
-
const filePath =
|
|
20888
|
-
const content = await
|
|
21255
|
+
const filePath = path44.join(this.globalPath, file);
|
|
21256
|
+
const content = await fs42.readFile(filePath, "utf-8");
|
|
20889
21257
|
filteredChars += content.length;
|
|
20890
21258
|
} catch {
|
|
20891
21259
|
}
|
|
20892
21260
|
}
|
|
20893
21261
|
for (const agent of agents) {
|
|
20894
21262
|
try {
|
|
20895
|
-
const agentPath =
|
|
20896
|
-
const content = await
|
|
21263
|
+
const agentPath = path44.join(this.globalPath, "agents", `${agent.name}.md`);
|
|
21264
|
+
const content = await fs42.readFile(agentPath, "utf-8");
|
|
20897
21265
|
filteredChars += content.length;
|
|
20898
21266
|
} catch {
|
|
20899
21267
|
}
|
|
@@ -20925,7 +21293,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
20925
21293
|
// ==========================================================================
|
|
20926
21294
|
async fileExists(filename) {
|
|
20927
21295
|
try {
|
|
20928
|
-
await
|
|
21296
|
+
await fs42.access(path44.join(this.projectPath, filename));
|
|
20929
21297
|
return true;
|
|
20930
21298
|
} catch {
|
|
20931
21299
|
return false;
|
|
@@ -20933,8 +21301,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
20933
21301
|
}
|
|
20934
21302
|
async getCliVersion() {
|
|
20935
21303
|
try {
|
|
20936
|
-
const pkgPath =
|
|
20937
|
-
const pkg = JSON.parse(await
|
|
21304
|
+
const pkgPath = path44.join(__dirname, "..", "..", "package.json");
|
|
21305
|
+
const pkg = JSON.parse(await fs42.readFile(pkgPath, "utf-8"));
|
|
20938
21306
|
return pkg.version || "0.0.0";
|
|
20939
21307
|
} catch {
|
|
20940
21308
|
return "0.0.0";
|
|
@@ -21093,24 +21461,24 @@ __export(uninstall_exports, {
|
|
|
21093
21461
|
UninstallCommands: () => UninstallCommands,
|
|
21094
21462
|
uninstall: () => uninstall
|
|
21095
21463
|
});
|
|
21096
|
-
import { execSync as
|
|
21464
|
+
import { execSync as execSync6 } from "node:child_process";
|
|
21097
21465
|
import fsSync2 from "node:fs";
|
|
21098
|
-
import
|
|
21466
|
+
import fs43 from "node:fs/promises";
|
|
21099
21467
|
import os12 from "node:os";
|
|
21100
|
-
import
|
|
21468
|
+
import path45 from "node:path";
|
|
21101
21469
|
import readline2 from "node:readline";
|
|
21102
21470
|
import chalk9 from "chalk";
|
|
21103
21471
|
async function getDirectorySize(dirPath) {
|
|
21104
21472
|
let totalSize = 0;
|
|
21105
21473
|
try {
|
|
21106
|
-
const entries = await
|
|
21474
|
+
const entries = await fs43.readdir(dirPath, { withFileTypes: true });
|
|
21107
21475
|
for (const entry of entries) {
|
|
21108
|
-
const entryPath =
|
|
21476
|
+
const entryPath = path45.join(dirPath, entry.name);
|
|
21109
21477
|
if (entry.isDirectory()) {
|
|
21110
21478
|
totalSize += await getDirectorySize(entryPath);
|
|
21111
21479
|
} else {
|
|
21112
21480
|
try {
|
|
21113
|
-
const stats = await
|
|
21481
|
+
const stats = await fs43.stat(entryPath);
|
|
21114
21482
|
totalSize += stats.size;
|
|
21115
21483
|
} catch {
|
|
21116
21484
|
}
|
|
@@ -21129,7 +21497,7 @@ function formatSize(bytes) {
|
|
|
21129
21497
|
}
|
|
21130
21498
|
async function countDirectoryItems(dirPath) {
|
|
21131
21499
|
try {
|
|
21132
|
-
const entries = await
|
|
21500
|
+
const entries = await fs43.readdir(dirPath, { withFileTypes: true });
|
|
21133
21501
|
return entries.filter((e) => e.isDirectory()).length;
|
|
21134
21502
|
} catch {
|
|
21135
21503
|
return 0;
|
|
@@ -21141,7 +21509,7 @@ function detectInstallation() {
|
|
|
21141
21509
|
npm: false
|
|
21142
21510
|
};
|
|
21143
21511
|
try {
|
|
21144
|
-
const result =
|
|
21512
|
+
const result = execSync6("brew list prjct-cli 2>/dev/null", { encoding: "utf-8" });
|
|
21145
21513
|
if (result) {
|
|
21146
21514
|
info.homebrew = true;
|
|
21147
21515
|
info.homebrewFormula = "prjct-cli";
|
|
@@ -21149,7 +21517,7 @@ function detectInstallation() {
|
|
|
21149
21517
|
} catch {
|
|
21150
21518
|
}
|
|
21151
21519
|
try {
|
|
21152
|
-
const result =
|
|
21520
|
+
const result = execSync6("npm list -g prjct-cli --depth=0 2>/dev/null", { encoding: "utf-8" });
|
|
21153
21521
|
if (result.includes("prjct-cli")) {
|
|
21154
21522
|
info.npm = true;
|
|
21155
21523
|
}
|
|
@@ -21162,7 +21530,7 @@ async function gatherUninstallItems() {
|
|
|
21162
21530
|
const providerPaths = getProviderPaths();
|
|
21163
21531
|
const prjctCliPath = path_manager_default.getGlobalBasePath();
|
|
21164
21532
|
const prjctCliExists = fsSync2.existsSync(prjctCliPath);
|
|
21165
|
-
const projectCount = prjctCliExists ? await countDirectoryItems(
|
|
21533
|
+
const projectCount = prjctCliExists ? await countDirectoryItems(path45.join(prjctCliPath, "projects")) : 0;
|
|
21166
21534
|
const prjctCliSize = prjctCliExists ? await getDirectorySize(prjctCliPath) : 0;
|
|
21167
21535
|
items.push({
|
|
21168
21536
|
path: prjctCliPath,
|
|
@@ -21172,7 +21540,7 @@ async function gatherUninstallItems() {
|
|
|
21172
21540
|
count: projectCount,
|
|
21173
21541
|
exists: prjctCliExists
|
|
21174
21542
|
});
|
|
21175
|
-
const claudeMdPath =
|
|
21543
|
+
const claudeMdPath = path45.join(providerPaths.claude.config, "CLAUDE.md");
|
|
21176
21544
|
const claudeMdExists = fsSync2.existsSync(claudeMdPath);
|
|
21177
21545
|
let hasPrjctSection = false;
|
|
21178
21546
|
if (claudeMdExists) {
|
|
@@ -21206,7 +21574,7 @@ async function gatherUninstallItems() {
|
|
|
21206
21574
|
description: "Claude router",
|
|
21207
21575
|
exists: claudeRouterExists
|
|
21208
21576
|
});
|
|
21209
|
-
const statusLinePath =
|
|
21577
|
+
const statusLinePath = path45.join(providerPaths.claude.config, "prjct-statusline.sh");
|
|
21210
21578
|
const statusLineExists = fsSync2.existsSync(statusLinePath);
|
|
21211
21579
|
items.push({
|
|
21212
21580
|
path: statusLinePath,
|
|
@@ -21222,7 +21590,7 @@ async function gatherUninstallItems() {
|
|
|
21222
21590
|
description: "Gemini router",
|
|
21223
21591
|
exists: geminiRouterExists
|
|
21224
21592
|
});
|
|
21225
|
-
const geminiMdPath =
|
|
21593
|
+
const geminiMdPath = path45.join(providerPaths.gemini.config, "GEMINI.md");
|
|
21226
21594
|
const geminiMdExists = fsSync2.existsSync(geminiMdPath);
|
|
21227
21595
|
let hasGeminiPrjctSection = false;
|
|
21228
21596
|
if (geminiMdExists) {
|
|
@@ -21244,7 +21612,7 @@ async function gatherUninstallItems() {
|
|
|
21244
21612
|
}
|
|
21245
21613
|
async function removePrjctSection(filePath) {
|
|
21246
21614
|
try {
|
|
21247
|
-
const content = await
|
|
21615
|
+
const content = await fs43.readFile(filePath, "utf-8");
|
|
21248
21616
|
if (!content.includes(PRJCT_START_MARKER) || !content.includes(PRJCT_END_MARKER)) {
|
|
21249
21617
|
return false;
|
|
21250
21618
|
}
|
|
@@ -21253,9 +21621,9 @@ async function removePrjctSection(filePath) {
|
|
|
21253
21621
|
let newContent = content.substring(0, startIndex) + content.substring(endIndex);
|
|
21254
21622
|
newContent = newContent.replace(/\n{3,}/g, "\n\n").trim();
|
|
21255
21623
|
if (!newContent || newContent.trim().length === 0) {
|
|
21256
|
-
await
|
|
21624
|
+
await fs43.unlink(filePath);
|
|
21257
21625
|
} else {
|
|
21258
|
-
await
|
|
21626
|
+
await fs43.writeFile(filePath, `${newContent}
|
|
21259
21627
|
`, "utf-8");
|
|
21260
21628
|
}
|
|
21261
21629
|
return true;
|
|
@@ -21266,12 +21634,12 @@ async function removePrjctSection(filePath) {
|
|
|
21266
21634
|
async function createBackup() {
|
|
21267
21635
|
const homeDir = os12.homedir();
|
|
21268
21636
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
|
|
21269
|
-
const backupDir =
|
|
21637
|
+
const backupDir = path45.join(homeDir, `.prjct-backup-${timestamp}`);
|
|
21270
21638
|
try {
|
|
21271
|
-
await
|
|
21639
|
+
await fs43.mkdir(backupDir, { recursive: true });
|
|
21272
21640
|
const prjctCliPath = path_manager_default.getGlobalBasePath();
|
|
21273
21641
|
if (fsSync2.existsSync(prjctCliPath)) {
|
|
21274
|
-
await copyDirectory(prjctCliPath,
|
|
21642
|
+
await copyDirectory(prjctCliPath, path45.join(backupDir, ".prjct-cli"));
|
|
21275
21643
|
}
|
|
21276
21644
|
return backupDir;
|
|
21277
21645
|
} catch {
|
|
@@ -21279,15 +21647,15 @@ async function createBackup() {
|
|
|
21279
21647
|
}
|
|
21280
21648
|
}
|
|
21281
21649
|
async function copyDirectory(src, dest) {
|
|
21282
|
-
await
|
|
21283
|
-
const entries = await
|
|
21650
|
+
await fs43.mkdir(dest, { recursive: true });
|
|
21651
|
+
const entries = await fs43.readdir(src, { withFileTypes: true });
|
|
21284
21652
|
for (const entry of entries) {
|
|
21285
|
-
const srcPath =
|
|
21286
|
-
const destPath =
|
|
21653
|
+
const srcPath = path45.join(src, entry.name);
|
|
21654
|
+
const destPath = path45.join(dest, entry.name);
|
|
21287
21655
|
if (entry.isDirectory()) {
|
|
21288
21656
|
await copyDirectory(srcPath, destPath);
|
|
21289
21657
|
} else {
|
|
21290
|
-
await
|
|
21658
|
+
await fs43.copyFile(srcPath, destPath);
|
|
21291
21659
|
}
|
|
21292
21660
|
}
|
|
21293
21661
|
}
|
|
@@ -21303,10 +21671,10 @@ async function performUninstall(items, installation, options) {
|
|
|
21303
21671
|
deleted.push(item.path);
|
|
21304
21672
|
}
|
|
21305
21673
|
} else if (item.type === "directory") {
|
|
21306
|
-
await
|
|
21674
|
+
await fs43.rm(item.path, { recursive: true, force: true });
|
|
21307
21675
|
deleted.push(item.path);
|
|
21308
21676
|
} else if (item.type === "file") {
|
|
21309
|
-
await
|
|
21677
|
+
await fs43.unlink(item.path);
|
|
21310
21678
|
deleted.push(item.path);
|
|
21311
21679
|
}
|
|
21312
21680
|
} catch (error) {
|
|
@@ -21317,7 +21685,7 @@ async function performUninstall(items, installation, options) {
|
|
|
21317
21685
|
if (installation.homebrew && installation.homebrewFormula) {
|
|
21318
21686
|
try {
|
|
21319
21687
|
if (!options.dryRun) {
|
|
21320
|
-
|
|
21688
|
+
execSync6(`brew uninstall ${installation.homebrewFormula}`, { stdio: "pipe" });
|
|
21321
21689
|
}
|
|
21322
21690
|
deleted.push("Homebrew: prjct-cli");
|
|
21323
21691
|
} catch (error) {
|
|
@@ -21327,7 +21695,7 @@ async function performUninstall(items, installation, options) {
|
|
|
21327
21695
|
if (installation.npm) {
|
|
21328
21696
|
try {
|
|
21329
21697
|
if (!options.dryRun) {
|
|
21330
|
-
|
|
21698
|
+
execSync6("npm uninstall -g prjct-cli", { stdio: "pipe" });
|
|
21331
21699
|
}
|
|
21332
21700
|
deleted.push("npm: prjct-cli");
|
|
21333
21701
|
} catch (error) {
|
|
@@ -21481,7 +21849,7 @@ __export(watch_service_exports, {
|
|
|
21481
21849
|
WatchService: () => WatchService,
|
|
21482
21850
|
watchService: () => watchService
|
|
21483
21851
|
});
|
|
21484
|
-
import
|
|
21852
|
+
import path46 from "node:path";
|
|
21485
21853
|
import chalk10 from "chalk";
|
|
21486
21854
|
import chokidar from "chokidar";
|
|
21487
21855
|
var TRIGGER_PATTERNS, IGNORE_PATTERNS2, WatchService, watchService;
|
|
@@ -21686,7 +22054,7 @@ ${chalk10.dim(`[${timestamp}]`)} ${chalk10.cyan("\u27F3")} ${filesSummary} chang
|
|
|
21686
22054
|
printStartup() {
|
|
21687
22055
|
console.log("");
|
|
21688
22056
|
console.log(chalk10.cyan("\u{1F441}\uFE0F Watching for changes..."));
|
|
21689
|
-
console.log(chalk10.dim(` Project: ${
|
|
22057
|
+
console.log(chalk10.dim(` Project: ${path46.basename(this.projectPath)}`));
|
|
21690
22058
|
console.log(chalk10.dim(` Debounce: ${this.options.debounceMs}ms`));
|
|
21691
22059
|
console.log(chalk10.dim(` Min interval: ${this.options.minIntervalMs / 1e3}s`));
|
|
21692
22060
|
console.log("");
|
|
@@ -22358,16 +22726,28 @@ __export(setup_exports, {
|
|
|
22358
22726
|
needsWindsurfRegeneration: () => needsWindsurfRegeneration,
|
|
22359
22727
|
run: () => run
|
|
22360
22728
|
});
|
|
22361
|
-
import { execSync as
|
|
22362
|
-
import
|
|
22729
|
+
import { execSync as execSync7 } from "node:child_process";
|
|
22730
|
+
import fs44 from "node:fs";
|
|
22363
22731
|
import os13 from "node:os";
|
|
22364
|
-
import
|
|
22732
|
+
import path47 from "node:path";
|
|
22365
22733
|
async function installAICLI(provider) {
|
|
22366
22734
|
const packageName = provider.name === "claude" ? "@anthropic-ai/claude-code" : "@google/gemini-cli";
|
|
22735
|
+
if (!dependencyValidator.isAvailable("npm")) {
|
|
22736
|
+
console.log(`${YELLOW4}\u26A0\uFE0F npm is not available${NC}`);
|
|
22737
|
+
console.log("");
|
|
22738
|
+
console.log(`${DIM4}Install ${provider.displayName} using one of:${NC}`);
|
|
22739
|
+
console.log(`${DIM4} \u2022 Install Node.js: https://nodejs.org${NC}`);
|
|
22740
|
+
console.log(
|
|
22741
|
+
`${DIM4} \u2022 Use Homebrew: brew install ${provider.name === "claude" ? "claude" : "gemini"}${NC}`
|
|
22742
|
+
);
|
|
22743
|
+
console.log(`${DIM4} \u2022 Use npx directly: npx ${packageName}${NC}`);
|
|
22744
|
+
console.log("");
|
|
22745
|
+
return false;
|
|
22746
|
+
}
|
|
22367
22747
|
try {
|
|
22368
22748
|
console.log(`${YELLOW4}\u{1F4E6} ${provider.displayName} not found. Installing...${NC}`);
|
|
22369
22749
|
console.log("");
|
|
22370
|
-
|
|
22750
|
+
execSync7(`npm install -g ${packageName}`, { stdio: "inherit" });
|
|
22371
22751
|
console.log("");
|
|
22372
22752
|
console.log(`${GREEN4}\u2713${NC} ${provider.displayName} installed successfully`);
|
|
22373
22753
|
console.log("");
|
|
@@ -22376,7 +22756,14 @@ async function installAICLI(provider) {
|
|
|
22376
22756
|
console.log(
|
|
22377
22757
|
`${YELLOW4}\u26A0\uFE0F Failed to install ${provider.displayName}: ${error.message}${NC}`
|
|
22378
22758
|
);
|
|
22379
|
-
console.log(
|
|
22759
|
+
console.log("");
|
|
22760
|
+
console.log(`${DIM4}Alternative installation methods:${NC}`);
|
|
22761
|
+
console.log(`${DIM4} \u2022 npm: npm install -g ${packageName}${NC}`);
|
|
22762
|
+
console.log(`${DIM4} \u2022 yarn: yarn global add ${packageName}${NC}`);
|
|
22763
|
+
console.log(`${DIM4} \u2022 pnpm: pnpm add -g ${packageName}${NC}`);
|
|
22764
|
+
console.log(
|
|
22765
|
+
`${DIM4} \u2022 brew: brew install ${provider.name === "claude" ? "claude" : "gemini"}${NC}`
|
|
22766
|
+
);
|
|
22380
22767
|
console.log("");
|
|
22381
22768
|
return false;
|
|
22382
22769
|
}
|
|
@@ -22467,12 +22854,12 @@ async function run() {
|
|
|
22467
22854
|
}
|
|
22468
22855
|
async function installGeminiRouter() {
|
|
22469
22856
|
try {
|
|
22470
|
-
const geminiCommandsDir =
|
|
22471
|
-
const routerSource =
|
|
22472
|
-
const routerDest =
|
|
22473
|
-
|
|
22474
|
-
if (
|
|
22475
|
-
|
|
22857
|
+
const geminiCommandsDir = path47.join(os13.homedir(), ".gemini", "commands");
|
|
22858
|
+
const routerSource = path47.join(getPackageRoot(), "templates", "commands", "p.toml");
|
|
22859
|
+
const routerDest = path47.join(geminiCommandsDir, "p.toml");
|
|
22860
|
+
fs44.mkdirSync(geminiCommandsDir, { recursive: true });
|
|
22861
|
+
if (fs44.existsSync(routerSource)) {
|
|
22862
|
+
fs44.copyFileSync(routerSource, routerDest);
|
|
22476
22863
|
return true;
|
|
22477
22864
|
}
|
|
22478
22865
|
return false;
|
|
@@ -22483,15 +22870,15 @@ async function installGeminiRouter() {
|
|
|
22483
22870
|
}
|
|
22484
22871
|
async function installGeminiGlobalConfig() {
|
|
22485
22872
|
try {
|
|
22486
|
-
const geminiDir =
|
|
22487
|
-
const globalConfigPath =
|
|
22488
|
-
const templatePath =
|
|
22489
|
-
|
|
22490
|
-
const templateContent =
|
|
22873
|
+
const geminiDir = path47.join(os13.homedir(), ".gemini");
|
|
22874
|
+
const globalConfigPath = path47.join(geminiDir, "GEMINI.md");
|
|
22875
|
+
const templatePath = path47.join(getPackageRoot(), "templates", "global", "GEMINI.md");
|
|
22876
|
+
fs44.mkdirSync(geminiDir, { recursive: true });
|
|
22877
|
+
const templateContent = fs44.readFileSync(templatePath, "utf-8");
|
|
22491
22878
|
let existingContent = "";
|
|
22492
22879
|
let fileExists2 = false;
|
|
22493
22880
|
try {
|
|
22494
|
-
existingContent =
|
|
22881
|
+
existingContent = fs44.readFileSync(globalConfigPath, "utf-8");
|
|
22495
22882
|
fileExists2 = true;
|
|
22496
22883
|
} catch (error) {
|
|
22497
22884
|
if (isNotFoundError(error)) {
|
|
@@ -22501,7 +22888,7 @@ async function installGeminiGlobalConfig() {
|
|
|
22501
22888
|
}
|
|
22502
22889
|
}
|
|
22503
22890
|
if (!fileExists2) {
|
|
22504
|
-
|
|
22891
|
+
fs44.writeFileSync(globalConfigPath, templateContent, "utf-8");
|
|
22505
22892
|
return { success: true, action: "created" };
|
|
22506
22893
|
}
|
|
22507
22894
|
const startMarker = "<!-- prjct:start - DO NOT REMOVE THIS MARKER -->";
|
|
@@ -22511,7 +22898,7 @@ async function installGeminiGlobalConfig() {
|
|
|
22511
22898
|
const updatedContent2 = `${existingContent}
|
|
22512
22899
|
|
|
22513
22900
|
${templateContent}`;
|
|
22514
|
-
|
|
22901
|
+
fs44.writeFileSync(globalConfigPath, updatedContent2, "utf-8");
|
|
22515
22902
|
return { success: true, action: "appended" };
|
|
22516
22903
|
}
|
|
22517
22904
|
const beforeMarker = existingContent.substring(0, existingContent.indexOf(startMarker));
|
|
@@ -22523,7 +22910,7 @@ ${templateContent}`;
|
|
|
22523
22910
|
templateContent.indexOf(endMarker) + endMarker.length
|
|
22524
22911
|
);
|
|
22525
22912
|
const updatedContent = beforeMarker + prjctSection + afterMarker;
|
|
22526
|
-
|
|
22913
|
+
fs44.writeFileSync(globalConfigPath, updatedContent, "utf-8");
|
|
22527
22914
|
return { success: true, action: "updated" };
|
|
22528
22915
|
} catch (error) {
|
|
22529
22916
|
console.error(`Gemini config warning: ${error.message}`);
|
|
@@ -22532,18 +22919,18 @@ ${templateContent}`;
|
|
|
22532
22919
|
}
|
|
22533
22920
|
async function installAntigravitySkill() {
|
|
22534
22921
|
try {
|
|
22535
|
-
const antigravitySkillsDir =
|
|
22536
|
-
const prjctSkillDir =
|
|
22537
|
-
const skillMdPath =
|
|
22538
|
-
const templatePath =
|
|
22539
|
-
|
|
22540
|
-
const fileExists2 =
|
|
22541
|
-
if (!
|
|
22922
|
+
const antigravitySkillsDir = path47.join(os13.homedir(), ".gemini", "antigravity", "skills");
|
|
22923
|
+
const prjctSkillDir = path47.join(antigravitySkillsDir, "prjct");
|
|
22924
|
+
const skillMdPath = path47.join(prjctSkillDir, "SKILL.md");
|
|
22925
|
+
const templatePath = path47.join(getPackageRoot(), "templates", "antigravity", "SKILL.md");
|
|
22926
|
+
fs44.mkdirSync(prjctSkillDir, { recursive: true });
|
|
22927
|
+
const fileExists2 = fs44.existsSync(skillMdPath);
|
|
22928
|
+
if (!fs44.existsSync(templatePath)) {
|
|
22542
22929
|
console.error("Antigravity SKILL.md template not found");
|
|
22543
22930
|
return { success: false, action: null };
|
|
22544
22931
|
}
|
|
22545
|
-
const templateContent =
|
|
22546
|
-
|
|
22932
|
+
const templateContent = fs44.readFileSync(templatePath, "utf-8");
|
|
22933
|
+
fs44.writeFileSync(skillMdPath, templateContent, "utf-8");
|
|
22547
22934
|
return { success: true, action: fileExists2 ? "updated" : "created" };
|
|
22548
22935
|
} catch (error) {
|
|
22549
22936
|
console.error(`Antigravity skill warning: ${error.message}`);
|
|
@@ -22562,24 +22949,24 @@ async function installCursorProject(projectRoot) {
|
|
|
22562
22949
|
gitignoreUpdated: false
|
|
22563
22950
|
};
|
|
22564
22951
|
try {
|
|
22565
|
-
const cursorDir =
|
|
22566
|
-
const rulesDir =
|
|
22567
|
-
const commandsDir =
|
|
22568
|
-
const routerMdcDest =
|
|
22569
|
-
const routerMdcSource =
|
|
22570
|
-
const cursorCommandsSource =
|
|
22571
|
-
|
|
22572
|
-
|
|
22573
|
-
if (
|
|
22574
|
-
|
|
22952
|
+
const cursorDir = path47.join(projectRoot, ".cursor");
|
|
22953
|
+
const rulesDir = path47.join(cursorDir, "rules");
|
|
22954
|
+
const commandsDir = path47.join(cursorDir, "commands");
|
|
22955
|
+
const routerMdcDest = path47.join(rulesDir, "prjct.mdc");
|
|
22956
|
+
const routerMdcSource = path47.join(getPackageRoot(), "templates", "cursor", "router.mdc");
|
|
22957
|
+
const cursorCommandsSource = path47.join(getPackageRoot(), "templates", "cursor", "commands");
|
|
22958
|
+
fs44.mkdirSync(rulesDir, { recursive: true });
|
|
22959
|
+
fs44.mkdirSync(commandsDir, { recursive: true });
|
|
22960
|
+
if (fs44.existsSync(routerMdcSource)) {
|
|
22961
|
+
fs44.copyFileSync(routerMdcSource, routerMdcDest);
|
|
22575
22962
|
result.rulesCreated = true;
|
|
22576
22963
|
}
|
|
22577
|
-
if (
|
|
22578
|
-
const commandFiles =
|
|
22964
|
+
if (fs44.existsSync(cursorCommandsSource)) {
|
|
22965
|
+
const commandFiles = fs44.readdirSync(cursorCommandsSource).filter((f) => f.endsWith(".md"));
|
|
22579
22966
|
for (const file of commandFiles) {
|
|
22580
|
-
const src =
|
|
22581
|
-
const dest =
|
|
22582
|
-
|
|
22967
|
+
const src = path47.join(cursorCommandsSource, file);
|
|
22968
|
+
const dest = path47.join(commandsDir, file);
|
|
22969
|
+
fs44.copyFileSync(src, dest);
|
|
22583
22970
|
}
|
|
22584
22971
|
result.commandsCreated = commandFiles.length > 0;
|
|
22585
22972
|
}
|
|
@@ -22593,7 +22980,7 @@ async function installCursorProject(projectRoot) {
|
|
|
22593
22980
|
}
|
|
22594
22981
|
async function addCursorToGitignore(projectRoot) {
|
|
22595
22982
|
try {
|
|
22596
|
-
const gitignorePath =
|
|
22983
|
+
const gitignorePath = path47.join(projectRoot, ".gitignore");
|
|
22597
22984
|
const entriesToAdd = [
|
|
22598
22985
|
"# prjct Cursor routers (regenerated per-developer)",
|
|
22599
22986
|
".cursor/rules/prjct.mdc",
|
|
@@ -22608,7 +22995,7 @@ async function addCursorToGitignore(projectRoot) {
|
|
|
22608
22995
|
let content = "";
|
|
22609
22996
|
let fileExists2 = false;
|
|
22610
22997
|
try {
|
|
22611
|
-
content =
|
|
22998
|
+
content = fs44.readFileSync(gitignorePath, "utf-8");
|
|
22612
22999
|
fileExists2 = true;
|
|
22613
23000
|
} catch (error) {
|
|
22614
23001
|
if (!isNotFoundError(error)) {
|
|
@@ -22623,7 +23010,7 @@ async function addCursorToGitignore(projectRoot) {
|
|
|
22623
23010
|
${entriesToAdd.join("\n")}
|
|
22624
23011
|
` : `${entriesToAdd.join("\n")}
|
|
22625
23012
|
`;
|
|
22626
|
-
|
|
23013
|
+
fs44.writeFileSync(gitignorePath, newContent, "utf-8");
|
|
22627
23014
|
return true;
|
|
22628
23015
|
} catch (error) {
|
|
22629
23016
|
console.error(`Gitignore update warning: ${error.message}`);
|
|
@@ -22631,12 +23018,12 @@ ${entriesToAdd.join("\n")}
|
|
|
22631
23018
|
}
|
|
22632
23019
|
}
|
|
22633
23020
|
function hasCursorProject(projectRoot) {
|
|
22634
|
-
return
|
|
23021
|
+
return fs44.existsSync(path47.join(projectRoot, ".cursor"));
|
|
22635
23022
|
}
|
|
22636
23023
|
function needsCursorRegeneration(projectRoot) {
|
|
22637
|
-
const cursorDir =
|
|
22638
|
-
const routerPath =
|
|
22639
|
-
return
|
|
23024
|
+
const cursorDir = path47.join(projectRoot, ".cursor");
|
|
23025
|
+
const routerPath = path47.join(cursorDir, "rules", "prjct.mdc");
|
|
23026
|
+
return fs44.existsSync(cursorDir) && !fs44.existsSync(routerPath);
|
|
22640
23027
|
}
|
|
22641
23028
|
async function installWindsurfProject(projectRoot) {
|
|
22642
23029
|
const result = {
|
|
@@ -22646,29 +23033,29 @@ async function installWindsurfProject(projectRoot) {
|
|
|
22646
23033
|
gitignoreUpdated: false
|
|
22647
23034
|
};
|
|
22648
23035
|
try {
|
|
22649
|
-
const windsurfDir =
|
|
22650
|
-
const rulesDir =
|
|
22651
|
-
const workflowsDir =
|
|
22652
|
-
const routerDest =
|
|
22653
|
-
const routerSource =
|
|
22654
|
-
const windsurfWorkflowsSource =
|
|
23036
|
+
const windsurfDir = path47.join(projectRoot, ".windsurf");
|
|
23037
|
+
const rulesDir = path47.join(windsurfDir, "rules");
|
|
23038
|
+
const workflowsDir = path47.join(windsurfDir, "workflows");
|
|
23039
|
+
const routerDest = path47.join(rulesDir, "prjct.md");
|
|
23040
|
+
const routerSource = path47.join(getPackageRoot(), "templates", "windsurf", "router.md");
|
|
23041
|
+
const windsurfWorkflowsSource = path47.join(
|
|
22655
23042
|
getPackageRoot(),
|
|
22656
23043
|
"templates",
|
|
22657
23044
|
"windsurf",
|
|
22658
23045
|
"workflows"
|
|
22659
23046
|
);
|
|
22660
|
-
|
|
22661
|
-
|
|
22662
|
-
if (
|
|
22663
|
-
|
|
23047
|
+
fs44.mkdirSync(rulesDir, { recursive: true });
|
|
23048
|
+
fs44.mkdirSync(workflowsDir, { recursive: true });
|
|
23049
|
+
if (fs44.existsSync(routerSource)) {
|
|
23050
|
+
fs44.copyFileSync(routerSource, routerDest);
|
|
22664
23051
|
result.rulesCreated = true;
|
|
22665
23052
|
}
|
|
22666
|
-
if (
|
|
22667
|
-
const workflowFiles =
|
|
23053
|
+
if (fs44.existsSync(windsurfWorkflowsSource)) {
|
|
23054
|
+
const workflowFiles = fs44.readdirSync(windsurfWorkflowsSource).filter((f) => f.endsWith(".md"));
|
|
22668
23055
|
for (const file of workflowFiles) {
|
|
22669
|
-
const src =
|
|
22670
|
-
const dest =
|
|
22671
|
-
|
|
23056
|
+
const src = path47.join(windsurfWorkflowsSource, file);
|
|
23057
|
+
const dest = path47.join(workflowsDir, file);
|
|
23058
|
+
fs44.copyFileSync(src, dest);
|
|
22672
23059
|
}
|
|
22673
23060
|
result.workflowsCreated = workflowFiles.length > 0;
|
|
22674
23061
|
}
|
|
@@ -22682,7 +23069,7 @@ async function installWindsurfProject(projectRoot) {
|
|
|
22682
23069
|
}
|
|
22683
23070
|
async function addWindsurfToGitignore(projectRoot) {
|
|
22684
23071
|
try {
|
|
22685
|
-
const gitignorePath =
|
|
23072
|
+
const gitignorePath = path47.join(projectRoot, ".gitignore");
|
|
22686
23073
|
const entriesToAdd = [
|
|
22687
23074
|
"# prjct Windsurf routers (regenerated per-developer)",
|
|
22688
23075
|
".windsurf/rules/prjct.md",
|
|
@@ -22697,7 +23084,7 @@ async function addWindsurfToGitignore(projectRoot) {
|
|
|
22697
23084
|
let content = "";
|
|
22698
23085
|
let fileExists2 = false;
|
|
22699
23086
|
try {
|
|
22700
|
-
content =
|
|
23087
|
+
content = fs44.readFileSync(gitignorePath, "utf-8");
|
|
22701
23088
|
fileExists2 = true;
|
|
22702
23089
|
} catch (error) {
|
|
22703
23090
|
if (!isNotFoundError(error)) {
|
|
@@ -22712,7 +23099,7 @@ async function addWindsurfToGitignore(projectRoot) {
|
|
|
22712
23099
|
${entriesToAdd.join("\n")}
|
|
22713
23100
|
` : `${entriesToAdd.join("\n")}
|
|
22714
23101
|
`;
|
|
22715
|
-
|
|
23102
|
+
fs44.writeFileSync(gitignorePath, newContent, "utf-8");
|
|
22716
23103
|
return true;
|
|
22717
23104
|
} catch (error) {
|
|
22718
23105
|
console.error(`Gitignore update warning: ${error.message}`);
|
|
@@ -22720,32 +23107,32 @@ ${entriesToAdd.join("\n")}
|
|
|
22720
23107
|
}
|
|
22721
23108
|
}
|
|
22722
23109
|
function hasWindsurfProject(projectRoot) {
|
|
22723
|
-
return
|
|
23110
|
+
return fs44.existsSync(path47.join(projectRoot, ".windsurf"));
|
|
22724
23111
|
}
|
|
22725
23112
|
function needsWindsurfRegeneration(projectRoot) {
|
|
22726
|
-
const windsurfDir =
|
|
22727
|
-
const routerPath =
|
|
22728
|
-
return
|
|
23113
|
+
const windsurfDir = path47.join(projectRoot, ".windsurf");
|
|
23114
|
+
const routerPath = path47.join(windsurfDir, "rules", "prjct.md");
|
|
23115
|
+
return fs44.existsSync(windsurfDir) && !fs44.existsSync(routerPath);
|
|
22729
23116
|
}
|
|
22730
23117
|
async function migrateProjectsCliVersion() {
|
|
22731
23118
|
try {
|
|
22732
|
-
const projectsDir =
|
|
22733
|
-
if (!
|
|
23119
|
+
const projectsDir = path47.join(os13.homedir(), ".prjct-cli", "projects");
|
|
23120
|
+
if (!fs44.existsSync(projectsDir)) {
|
|
22734
23121
|
return;
|
|
22735
23122
|
}
|
|
22736
|
-
const projectDirs =
|
|
23123
|
+
const projectDirs = fs44.readdirSync(projectsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
22737
23124
|
let migrated = 0;
|
|
22738
23125
|
for (const projectId of projectDirs) {
|
|
22739
|
-
const projectJsonPath =
|
|
22740
|
-
if (!
|
|
23126
|
+
const projectJsonPath = path47.join(projectsDir, projectId, "project.json");
|
|
23127
|
+
if (!fs44.existsSync(projectJsonPath)) {
|
|
22741
23128
|
continue;
|
|
22742
23129
|
}
|
|
22743
23130
|
try {
|
|
22744
|
-
const content =
|
|
23131
|
+
const content = fs44.readFileSync(projectJsonPath, "utf8");
|
|
22745
23132
|
const project = JSON.parse(content);
|
|
22746
23133
|
if (project.cliVersion !== VERSION) {
|
|
22747
23134
|
project.cliVersion = VERSION;
|
|
22748
|
-
|
|
23135
|
+
fs44.writeFileSync(projectJsonPath, JSON.stringify(project, null, 2));
|
|
22749
23136
|
migrated++;
|
|
22750
23137
|
}
|
|
22751
23138
|
} catch (error) {
|
|
@@ -22765,9 +23152,9 @@ async function migrateProjectsCliVersion() {
|
|
|
22765
23152
|
}
|
|
22766
23153
|
function ensureStatusLineSettings(settingsPath, statusLinePath) {
|
|
22767
23154
|
let settings = {};
|
|
22768
|
-
if (
|
|
23155
|
+
if (fs44.existsSync(settingsPath)) {
|
|
22769
23156
|
try {
|
|
22770
|
-
settings = JSON.parse(
|
|
23157
|
+
settings = JSON.parse(fs44.readFileSync(settingsPath, "utf8"));
|
|
22771
23158
|
} catch (error) {
|
|
22772
23159
|
if (!(error instanceof SyntaxError)) {
|
|
22773
23160
|
throw error;
|
|
@@ -22775,42 +23162,42 @@ function ensureStatusLineSettings(settingsPath, statusLinePath) {
|
|
|
22775
23162
|
}
|
|
22776
23163
|
}
|
|
22777
23164
|
settings.statusLine = { type: "command", command: statusLinePath };
|
|
22778
|
-
|
|
23165
|
+
fs44.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
22779
23166
|
}
|
|
22780
23167
|
async function installStatusLine() {
|
|
22781
23168
|
try {
|
|
22782
|
-
const claudeDir =
|
|
22783
|
-
const settingsPath =
|
|
22784
|
-
const claudeStatusLinePath =
|
|
22785
|
-
const prjctStatusLineDir =
|
|
22786
|
-
const prjctStatusLinePath =
|
|
22787
|
-
const prjctThemesDir =
|
|
22788
|
-
const prjctLibDir =
|
|
22789
|
-
const prjctComponentsDir =
|
|
22790
|
-
const prjctConfigPath =
|
|
22791
|
-
const assetsDir =
|
|
22792
|
-
const sourceScript =
|
|
22793
|
-
const sourceThemeDir =
|
|
22794
|
-
const sourceLibDir =
|
|
22795
|
-
const sourceComponentsDir =
|
|
22796
|
-
const sourceConfigPath =
|
|
22797
|
-
if (!
|
|
22798
|
-
|
|
23169
|
+
const claudeDir = path47.join(os13.homedir(), ".claude");
|
|
23170
|
+
const settingsPath = path47.join(claudeDir, "settings.json");
|
|
23171
|
+
const claudeStatusLinePath = path47.join(claudeDir, "prjct-statusline.sh");
|
|
23172
|
+
const prjctStatusLineDir = path47.join(os13.homedir(), ".prjct-cli", "statusline");
|
|
23173
|
+
const prjctStatusLinePath = path47.join(prjctStatusLineDir, "statusline.sh");
|
|
23174
|
+
const prjctThemesDir = path47.join(prjctStatusLineDir, "themes");
|
|
23175
|
+
const prjctLibDir = path47.join(prjctStatusLineDir, "lib");
|
|
23176
|
+
const prjctComponentsDir = path47.join(prjctStatusLineDir, "components");
|
|
23177
|
+
const prjctConfigPath = path47.join(prjctStatusLineDir, "config.json");
|
|
23178
|
+
const assetsDir = path47.join(getPackageRoot(), "assets", "statusline");
|
|
23179
|
+
const sourceScript = path47.join(assetsDir, "statusline.sh");
|
|
23180
|
+
const sourceThemeDir = path47.join(assetsDir, "themes");
|
|
23181
|
+
const sourceLibDir = path47.join(assetsDir, "lib");
|
|
23182
|
+
const sourceComponentsDir = path47.join(assetsDir, "components");
|
|
23183
|
+
const sourceConfigPath = path47.join(assetsDir, "default-config.json");
|
|
23184
|
+
if (!fs44.existsSync(claudeDir)) {
|
|
23185
|
+
fs44.mkdirSync(claudeDir, { recursive: true });
|
|
22799
23186
|
}
|
|
22800
|
-
if (!
|
|
22801
|
-
|
|
23187
|
+
if (!fs44.existsSync(prjctStatusLineDir)) {
|
|
23188
|
+
fs44.mkdirSync(prjctStatusLineDir, { recursive: true });
|
|
22802
23189
|
}
|
|
22803
|
-
if (!
|
|
22804
|
-
|
|
23190
|
+
if (!fs44.existsSync(prjctThemesDir)) {
|
|
23191
|
+
fs44.mkdirSync(prjctThemesDir, { recursive: true });
|
|
22805
23192
|
}
|
|
22806
|
-
if (!
|
|
22807
|
-
|
|
23193
|
+
if (!fs44.existsSync(prjctLibDir)) {
|
|
23194
|
+
fs44.mkdirSync(prjctLibDir, { recursive: true });
|
|
22808
23195
|
}
|
|
22809
|
-
if (!
|
|
22810
|
-
|
|
23196
|
+
if (!fs44.existsSync(prjctComponentsDir)) {
|
|
23197
|
+
fs44.mkdirSync(prjctComponentsDir, { recursive: true });
|
|
22811
23198
|
}
|
|
22812
|
-
if (
|
|
22813
|
-
const existingContent =
|
|
23199
|
+
if (fs44.existsSync(prjctStatusLinePath)) {
|
|
23200
|
+
const existingContent = fs44.readFileSync(prjctStatusLinePath, "utf8");
|
|
22814
23201
|
if (existingContent.includes("CLI_VERSION=")) {
|
|
22815
23202
|
const versionMatch = existingContent.match(/CLI_VERSION="([^"]*)"/);
|
|
22816
23203
|
if (versionMatch && versionMatch[1] !== VERSION) {
|
|
@@ -22818,7 +23205,7 @@ async function installStatusLine() {
|
|
|
22818
23205
|
/CLI_VERSION="[^"]*"/,
|
|
22819
23206
|
`CLI_VERSION="${VERSION}"`
|
|
22820
23207
|
);
|
|
22821
|
-
|
|
23208
|
+
fs44.writeFileSync(prjctStatusLinePath, updatedContent, { mode: 493 });
|
|
22822
23209
|
}
|
|
22823
23210
|
installStatusLineModules(sourceLibDir, prjctLibDir);
|
|
22824
23211
|
installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
|
|
@@ -22827,22 +23214,22 @@ async function installStatusLine() {
|
|
|
22827
23214
|
return;
|
|
22828
23215
|
}
|
|
22829
23216
|
}
|
|
22830
|
-
if (
|
|
22831
|
-
let scriptContent =
|
|
23217
|
+
if (fs44.existsSync(sourceScript)) {
|
|
23218
|
+
let scriptContent = fs44.readFileSync(sourceScript, "utf8");
|
|
22832
23219
|
scriptContent = scriptContent.replace(/CLI_VERSION="[^"]*"/, `CLI_VERSION="${VERSION}"`);
|
|
22833
|
-
|
|
23220
|
+
fs44.writeFileSync(prjctStatusLinePath, scriptContent, { mode: 493 });
|
|
22834
23221
|
installStatusLineModules(sourceLibDir, prjctLibDir);
|
|
22835
23222
|
installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
|
|
22836
|
-
if (
|
|
22837
|
-
const themes =
|
|
23223
|
+
if (fs44.existsSync(sourceThemeDir)) {
|
|
23224
|
+
const themes = fs44.readdirSync(sourceThemeDir);
|
|
22838
23225
|
for (const theme of themes) {
|
|
22839
|
-
const src =
|
|
22840
|
-
const dest =
|
|
22841
|
-
|
|
23226
|
+
const src = path47.join(sourceThemeDir, theme);
|
|
23227
|
+
const dest = path47.join(prjctThemesDir, theme);
|
|
23228
|
+
fs44.copyFileSync(src, dest);
|
|
22842
23229
|
}
|
|
22843
23230
|
}
|
|
22844
|
-
if (!
|
|
22845
|
-
|
|
23231
|
+
if (!fs44.existsSync(prjctConfigPath) && fs44.existsSync(sourceConfigPath)) {
|
|
23232
|
+
fs44.copyFileSync(sourceConfigPath, prjctConfigPath);
|
|
22846
23233
|
}
|
|
22847
23234
|
} else {
|
|
22848
23235
|
const scriptContent = `#!/bin/bash
|
|
@@ -22877,7 +23264,7 @@ if [ -f "$CONFIG" ]; then
|
|
|
22877
23264
|
fi
|
|
22878
23265
|
echo "prjct"
|
|
22879
23266
|
`;
|
|
22880
|
-
|
|
23267
|
+
fs44.writeFileSync(prjctStatusLinePath, scriptContent, { mode: 493 });
|
|
22881
23268
|
}
|
|
22882
23269
|
ensureStatusLineSymlink(claudeStatusLinePath, prjctStatusLinePath);
|
|
22883
23270
|
ensureStatusLineSettings(settingsPath, claudeStatusLinePath);
|
|
@@ -22889,10 +23276,10 @@ echo "prjct"
|
|
|
22889
23276
|
}
|
|
22890
23277
|
async function installContext7MCP() {
|
|
22891
23278
|
try {
|
|
22892
|
-
const claudeDir =
|
|
22893
|
-
const mcpConfigPath =
|
|
22894
|
-
if (!
|
|
22895
|
-
|
|
23279
|
+
const claudeDir = path47.join(os13.homedir(), ".claude");
|
|
23280
|
+
const mcpConfigPath = path47.join(claudeDir, "mcp.json");
|
|
23281
|
+
if (!fs44.existsSync(claudeDir)) {
|
|
23282
|
+
fs44.mkdirSync(claudeDir, { recursive: true });
|
|
22896
23283
|
}
|
|
22897
23284
|
const context7Config = {
|
|
22898
23285
|
mcpServers: {
|
|
@@ -22902,54 +23289,54 @@ async function installContext7MCP() {
|
|
|
22902
23289
|
}
|
|
22903
23290
|
}
|
|
22904
23291
|
};
|
|
22905
|
-
if (
|
|
22906
|
-
const existingContent =
|
|
23292
|
+
if (fs44.existsSync(mcpConfigPath)) {
|
|
23293
|
+
const existingContent = fs44.readFileSync(mcpConfigPath, "utf-8");
|
|
22907
23294
|
const existingConfig = JSON.parse(existingContent);
|
|
22908
23295
|
if (existingConfig.mcpServers?.context7) {
|
|
22909
23296
|
return;
|
|
22910
23297
|
}
|
|
22911
23298
|
existingConfig.mcpServers = existingConfig.mcpServers || {};
|
|
22912
23299
|
existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
|
|
22913
|
-
|
|
23300
|
+
fs44.writeFileSync(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
|
|
22914
23301
|
} else {
|
|
22915
|
-
|
|
23302
|
+
fs44.writeFileSync(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
|
|
22916
23303
|
}
|
|
22917
23304
|
} catch (error) {
|
|
22918
23305
|
console.error(`Context7 MCP setup warning: ${error.message}`);
|
|
22919
23306
|
}
|
|
22920
23307
|
}
|
|
22921
23308
|
function installStatusLineModules(sourceDir, destDir) {
|
|
22922
|
-
if (!
|
|
23309
|
+
if (!fs44.existsSync(sourceDir)) {
|
|
22923
23310
|
return;
|
|
22924
23311
|
}
|
|
22925
|
-
const files =
|
|
23312
|
+
const files = fs44.readdirSync(sourceDir);
|
|
22926
23313
|
for (const file of files) {
|
|
22927
23314
|
if (file.endsWith(".sh")) {
|
|
22928
|
-
const src =
|
|
22929
|
-
const dest =
|
|
22930
|
-
|
|
22931
|
-
|
|
23315
|
+
const src = path47.join(sourceDir, file);
|
|
23316
|
+
const dest = path47.join(destDir, file);
|
|
23317
|
+
fs44.copyFileSync(src, dest);
|
|
23318
|
+
fs44.chmodSync(dest, 493);
|
|
22932
23319
|
}
|
|
22933
23320
|
}
|
|
22934
23321
|
}
|
|
22935
23322
|
function ensureStatusLineSymlink(linkPath, targetPath) {
|
|
22936
23323
|
try {
|
|
22937
|
-
if (
|
|
22938
|
-
const stats =
|
|
23324
|
+
if (fs44.existsSync(linkPath)) {
|
|
23325
|
+
const stats = fs44.lstatSync(linkPath);
|
|
22939
23326
|
if (stats.isSymbolicLink()) {
|
|
22940
|
-
const existingTarget =
|
|
23327
|
+
const existingTarget = fs44.readlinkSync(linkPath);
|
|
22941
23328
|
if (existingTarget === targetPath) {
|
|
22942
23329
|
return;
|
|
22943
23330
|
}
|
|
22944
23331
|
}
|
|
22945
|
-
|
|
23332
|
+
fs44.unlinkSync(linkPath);
|
|
22946
23333
|
}
|
|
22947
|
-
|
|
23334
|
+
fs44.symlinkSync(targetPath, linkPath);
|
|
22948
23335
|
} catch (_error) {
|
|
22949
23336
|
try {
|
|
22950
|
-
if (
|
|
22951
|
-
|
|
22952
|
-
|
|
23337
|
+
if (fs44.existsSync(targetPath)) {
|
|
23338
|
+
fs44.copyFileSync(targetPath, linkPath);
|
|
23339
|
+
fs44.chmodSync(linkPath, 493);
|
|
22953
23340
|
}
|
|
22954
23341
|
} catch (copyError) {
|
|
22955
23342
|
if (!isNotFoundError(copyError)) {
|
|
@@ -22987,6 +23374,7 @@ var GREEN4, YELLOW4, DIM4, NC, setup_default, isDirectRun;
|
|
|
22987
23374
|
var init_setup = __esm({
|
|
22988
23375
|
"core/infrastructure/setup.ts"() {
|
|
22989
23376
|
"use strict";
|
|
23377
|
+
init_dependency_validator();
|
|
22990
23378
|
init_fs();
|
|
22991
23379
|
init_version();
|
|
22992
23380
|
init_ai_provider();
|
|
@@ -23364,7 +23752,7 @@ var init_registry2 = __esm({
|
|
|
23364
23752
|
});
|
|
23365
23753
|
|
|
23366
23754
|
// core/commands/analytics.ts
|
|
23367
|
-
import
|
|
23755
|
+
import path48 from "node:path";
|
|
23368
23756
|
var AnalyticsCommands;
|
|
23369
23757
|
var init_analytics = __esm({
|
|
23370
23758
|
"core/commands/analytics.ts"() {
|
|
@@ -23390,7 +23778,7 @@ var init_analytics = __esm({
|
|
|
23390
23778
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
23391
23779
|
return { success: false, error: "No project ID found" };
|
|
23392
23780
|
}
|
|
23393
|
-
const projectName =
|
|
23781
|
+
const projectName = path48.basename(projectPath);
|
|
23394
23782
|
const currentTask = await stateStorage.getCurrentTask(projectId);
|
|
23395
23783
|
const queueTasks = await queueStorage.getActiveTasks(projectId);
|
|
23396
23784
|
const shipped = await shippedStorage.getRecent(projectId, 5);
|
|
@@ -23642,8 +24030,8 @@ ${"\u2550".repeat(50)}
|
|
|
23642
24030
|
});
|
|
23643
24031
|
|
|
23644
24032
|
// core/commands/context.ts
|
|
23645
|
-
import
|
|
23646
|
-
import
|
|
24033
|
+
import fs45 from "node:fs/promises";
|
|
24034
|
+
import path49 from "node:path";
|
|
23647
24035
|
var ContextCommands, contextCommands;
|
|
23648
24036
|
var init_context = __esm({
|
|
23649
24037
|
"core/commands/context.ts"() {
|
|
@@ -23769,8 +24157,8 @@ var init_context = __esm({
|
|
|
23769
24157
|
*/
|
|
23770
24158
|
async loadRepoAnalysis(globalPath) {
|
|
23771
24159
|
try {
|
|
23772
|
-
const analysisPath =
|
|
23773
|
-
const content = await
|
|
24160
|
+
const analysisPath = path49.join(globalPath, "analysis", "repo-analysis.json");
|
|
24161
|
+
const content = await fs45.readFile(analysisPath, "utf-8");
|
|
23774
24162
|
const data = JSON.parse(content);
|
|
23775
24163
|
return {
|
|
23776
24164
|
ecosystem: data.ecosystem || "unknown",
|
|
@@ -23789,7 +24177,7 @@ var init_context = __esm({
|
|
|
23789
24177
|
});
|
|
23790
24178
|
|
|
23791
24179
|
// core/commands/cleanup.ts
|
|
23792
|
-
import
|
|
24180
|
+
import path50 from "node:path";
|
|
23793
24181
|
async function cleanupMemory(projectPath) {
|
|
23794
24182
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
23795
24183
|
const results = { rotated: [], totalSize: 0, freedSpace: 0 };
|
|
@@ -23805,7 +24193,7 @@ async function cleanupMemory(projectPath) {
|
|
|
23805
24193
|
results.totalSize += sizeMB;
|
|
23806
24194
|
const rotated = await jsonl_helper_default.rotateJsonLinesIfNeeded(filePath, 10);
|
|
23807
24195
|
if (rotated) {
|
|
23808
|
-
results.rotated.push(
|
|
24196
|
+
results.rotated.push(path50.basename(filePath));
|
|
23809
24197
|
results.freedSpace += sizeMB;
|
|
23810
24198
|
}
|
|
23811
24199
|
}
|
|
@@ -23912,7 +24300,7 @@ var init_cleanup = __esm({
|
|
|
23912
24300
|
});
|
|
23913
24301
|
|
|
23914
24302
|
// core/commands/design.ts
|
|
23915
|
-
import
|
|
24303
|
+
import path51 from "node:path";
|
|
23916
24304
|
async function design(target = null, options = {}, projectPath = process.cwd()) {
|
|
23917
24305
|
try {
|
|
23918
24306
|
const designType = options.type || "architecture";
|
|
@@ -23924,7 +24312,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
|
|
|
23924
24312
|
const designTarget = target || "system";
|
|
23925
24313
|
output_default.spin(`designing ${designType}...`);
|
|
23926
24314
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
23927
|
-
const designsPath =
|
|
24315
|
+
const designsPath = path51.join(
|
|
23928
24316
|
path_manager_default.getGlobalProjectPath(projectId),
|
|
23929
24317
|
"planning",
|
|
23930
24318
|
"designs"
|
|
@@ -23964,7 +24352,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
|
|
|
23964
24352
|
break;
|
|
23965
24353
|
}
|
|
23966
24354
|
const designFileName = `${designType}-${designTarget.toLowerCase().replace(/\s+/g, "-")}.md`;
|
|
23967
|
-
const designFilePath =
|
|
24355
|
+
const designFilePath = path51.join(designsPath, designFileName);
|
|
23968
24356
|
await file_helper_exports.writeFile(designFilePath, designContent);
|
|
23969
24357
|
await memoryService.log(projectPath, "design_created", {
|
|
23970
24358
|
type: designType,
|
|
@@ -23988,7 +24376,7 @@ var init_design = __esm({
|
|
|
23988
24376
|
});
|
|
23989
24377
|
|
|
23990
24378
|
// core/commands/snapshots.ts
|
|
23991
|
-
import
|
|
24379
|
+
import path52 from "node:path";
|
|
23992
24380
|
async function recover(projectPath = process.cwd()) {
|
|
23993
24381
|
try {
|
|
23994
24382
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
@@ -24040,11 +24428,11 @@ async function undo(projectPath = process.cwd()) {
|
|
|
24040
24428
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
24041
24429
|
return { success: false, error: "No project ID found" };
|
|
24042
24430
|
}
|
|
24043
|
-
const snapshotsPath =
|
|
24431
|
+
const snapshotsPath = path52.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
24044
24432
|
await file_helper_exports.ensureDir(snapshotsPath);
|
|
24045
|
-
const { execSync:
|
|
24433
|
+
const { execSync: execSync8 } = await import("node:child_process");
|
|
24046
24434
|
try {
|
|
24047
|
-
const status =
|
|
24435
|
+
const status = execSync8("git status --porcelain", {
|
|
24048
24436
|
cwd: projectPath,
|
|
24049
24437
|
encoding: "utf-8"
|
|
24050
24438
|
}).trim();
|
|
@@ -24054,11 +24442,11 @@ async function undo(projectPath = process.cwd()) {
|
|
|
24054
24442
|
}
|
|
24055
24443
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
24056
24444
|
const stashMessage = `prjct-undo-${timestamp}`;
|
|
24057
|
-
|
|
24445
|
+
execSync8(`git stash push -m "${stashMessage}"`, {
|
|
24058
24446
|
cwd: projectPath,
|
|
24059
24447
|
encoding: "utf-8"
|
|
24060
24448
|
});
|
|
24061
|
-
const snapshotFile =
|
|
24449
|
+
const snapshotFile = path52.join(snapshotsPath, "history.json");
|
|
24062
24450
|
let history2 = { snapshots: [], current: -1 };
|
|
24063
24451
|
try {
|
|
24064
24452
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -24098,8 +24486,8 @@ async function redo(projectPath = process.cwd()) {
|
|
|
24098
24486
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
24099
24487
|
return { success: false, error: "No project ID found" };
|
|
24100
24488
|
}
|
|
24101
|
-
const snapshotsPath =
|
|
24102
|
-
const snapshotFile =
|
|
24489
|
+
const snapshotsPath = path52.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
24490
|
+
const snapshotFile = path52.join(snapshotsPath, "history.json");
|
|
24103
24491
|
let history2;
|
|
24104
24492
|
try {
|
|
24105
24493
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -24115,9 +24503,9 @@ async function redo(projectPath = process.cwd()) {
|
|
|
24115
24503
|
output_default.warn("nothing to redo");
|
|
24116
24504
|
return { success: false, message: "Nothing to redo" };
|
|
24117
24505
|
}
|
|
24118
|
-
const { execSync:
|
|
24506
|
+
const { execSync: execSync8 } = await import("node:child_process");
|
|
24119
24507
|
try {
|
|
24120
|
-
const stashList =
|
|
24508
|
+
const stashList = execSync8("git stash list", {
|
|
24121
24509
|
cwd: projectPath,
|
|
24122
24510
|
encoding: "utf-8"
|
|
24123
24511
|
}).trim();
|
|
@@ -24130,7 +24518,7 @@ async function redo(projectPath = process.cwd()) {
|
|
|
24130
24518
|
output_default.warn("no prjct undo point found");
|
|
24131
24519
|
return { success: false, message: "No prjct undo point found" };
|
|
24132
24520
|
}
|
|
24133
|
-
|
|
24521
|
+
execSync8("git stash pop", {
|
|
24134
24522
|
cwd: projectPath,
|
|
24135
24523
|
encoding: "utf-8"
|
|
24136
24524
|
});
|
|
@@ -24158,8 +24546,8 @@ async function history(projectPath = process.cwd()) {
|
|
|
24158
24546
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
24159
24547
|
return { success: false, error: "No project ID found" };
|
|
24160
24548
|
}
|
|
24161
|
-
const snapshotsPath =
|
|
24162
|
-
const snapshotFile =
|
|
24549
|
+
const snapshotsPath = path52.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
24550
|
+
const snapshotFile = path52.join(snapshotsPath, "history.json");
|
|
24163
24551
|
let snapshotHistory;
|
|
24164
24552
|
try {
|
|
24165
24553
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -24266,8 +24654,8 @@ var init_maintenance = __esm({
|
|
|
24266
24654
|
});
|
|
24267
24655
|
|
|
24268
24656
|
// core/commands/setup.ts
|
|
24269
|
-
import
|
|
24270
|
-
import
|
|
24657
|
+
import fs46 from "node:fs";
|
|
24658
|
+
import path53 from "node:path";
|
|
24271
24659
|
import chalk11 from "chalk";
|
|
24272
24660
|
var SetupCommands;
|
|
24273
24661
|
var init_setup2 = __esm({
|
|
@@ -24394,7 +24782,7 @@ Please install it first:
|
|
|
24394
24782
|
try {
|
|
24395
24783
|
const claudeDir = path_manager_default.getClaudeDir();
|
|
24396
24784
|
const settingsPath = path_manager_default.getClaudeSettingsPath();
|
|
24397
|
-
const statusLinePath =
|
|
24785
|
+
const statusLinePath = path53.join(claudeDir, "prjct-statusline.sh");
|
|
24398
24786
|
const scriptContent = `#!/bin/bash
|
|
24399
24787
|
# prjct Status Line for Claude Code
|
|
24400
24788
|
# Shows version update notifications and current task
|
|
@@ -24452,11 +24840,11 @@ fi
|
|
|
24452
24840
|
# Default: show prjct branding
|
|
24453
24841
|
echo "\u26A1 prjct"
|
|
24454
24842
|
`;
|
|
24455
|
-
|
|
24843
|
+
fs46.writeFileSync(statusLinePath, scriptContent, { mode: 493 });
|
|
24456
24844
|
let settings = {};
|
|
24457
|
-
if (
|
|
24845
|
+
if (fs46.existsSync(settingsPath)) {
|
|
24458
24846
|
try {
|
|
24459
|
-
settings = JSON.parse(
|
|
24847
|
+
settings = JSON.parse(fs46.readFileSync(settingsPath, "utf8"));
|
|
24460
24848
|
} catch (_error) {
|
|
24461
24849
|
}
|
|
24462
24850
|
}
|
|
@@ -24464,7 +24852,7 @@ echo "\u26A1 prjct"
|
|
|
24464
24852
|
type: "command",
|
|
24465
24853
|
command: statusLinePath
|
|
24466
24854
|
};
|
|
24467
|
-
|
|
24855
|
+
fs46.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
24468
24856
|
return { success: true };
|
|
24469
24857
|
} catch (error) {
|
|
24470
24858
|
return { success: false, error: error.message };
|
|
@@ -24520,18 +24908,18 @@ echo "\u26A1 prjct"
|
|
|
24520
24908
|
});
|
|
24521
24909
|
|
|
24522
24910
|
// core/utils/project-commands.ts
|
|
24523
|
-
import
|
|
24911
|
+
import path54 from "node:path";
|
|
24524
24912
|
async function detectPackageManager(projectPath, pkg) {
|
|
24525
24913
|
const declared = pkg?.packageManager?.trim().toLowerCase();
|
|
24526
24914
|
if (declared?.startsWith("pnpm@")) return "pnpm";
|
|
24527
24915
|
if (declared?.startsWith("yarn@")) return "yarn";
|
|
24528
24916
|
if (declared?.startsWith("bun@")) return "bun";
|
|
24529
24917
|
if (declared?.startsWith("npm@")) return "npm";
|
|
24530
|
-
if (await fileExists(
|
|
24531
|
-
if (await fileExists(
|
|
24532
|
-
if (await fileExists(
|
|
24533
|
-
if (await fileExists(
|
|
24534
|
-
if (await fileExists(
|
|
24918
|
+
if (await fileExists(path54.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
|
|
24919
|
+
if (await fileExists(path54.join(projectPath, "yarn.lock"))) return "yarn";
|
|
24920
|
+
if (await fileExists(path54.join(projectPath, "bun.lockb"))) return "bun";
|
|
24921
|
+
if (await fileExists(path54.join(projectPath, "bun.lock"))) return "bun";
|
|
24922
|
+
if (await fileExists(path54.join(projectPath, "package-lock.json"))) return "npm";
|
|
24535
24923
|
return "npm";
|
|
24536
24924
|
}
|
|
24537
24925
|
function pmRun(pm, scriptName) {
|
|
@@ -24547,7 +24935,7 @@ function pmTest(pm) {
|
|
|
24547
24935
|
return "npm test";
|
|
24548
24936
|
}
|
|
24549
24937
|
async function detectProjectCommands(projectPath) {
|
|
24550
|
-
const pkgPath =
|
|
24938
|
+
const pkgPath = path54.join(projectPath, "package.json");
|
|
24551
24939
|
const pkg = await readJson(pkgPath, null);
|
|
24552
24940
|
if (pkg) {
|
|
24553
24941
|
const pm = await detectPackageManager(projectPath, pkg);
|
|
@@ -24564,27 +24952,27 @@ async function detectProjectCommands(projectPath) {
|
|
|
24564
24952
|
}
|
|
24565
24953
|
return result;
|
|
24566
24954
|
}
|
|
24567
|
-
if (await fileExists(
|
|
24955
|
+
if (await fileExists(path54.join(projectPath, "pytest.ini"))) {
|
|
24568
24956
|
return { stack: "python", test: { tool: "pytest", command: "pytest" } };
|
|
24569
24957
|
}
|
|
24570
|
-
const pyproject = await readFile(
|
|
24958
|
+
const pyproject = await readFile(path54.join(projectPath, "pyproject.toml"), "");
|
|
24571
24959
|
if (pyproject.includes("[tool.pytest") || pyproject.includes("pytest")) {
|
|
24572
24960
|
return { stack: "python", test: { tool: "pytest", command: "pytest" } };
|
|
24573
24961
|
}
|
|
24574
|
-
if (await fileExists(
|
|
24962
|
+
if (await fileExists(path54.join(projectPath, "Cargo.toml"))) {
|
|
24575
24963
|
return { stack: "rust", test: { tool: "cargo", command: "cargo test" } };
|
|
24576
24964
|
}
|
|
24577
|
-
if (await fileExists(
|
|
24965
|
+
if (await fileExists(path54.join(projectPath, "go.mod"))) {
|
|
24578
24966
|
return { stack: "go", test: { tool: "go", command: "go test ./..." } };
|
|
24579
24967
|
}
|
|
24580
24968
|
const files = await listFiles(projectPath);
|
|
24581
24969
|
if (files.some((f) => f.endsWith(".sln") || f.endsWith(".csproj") || f.endsWith(".fsproj"))) {
|
|
24582
24970
|
return { stack: "dotnet", test: { tool: "dotnet", command: "dotnet test" } };
|
|
24583
24971
|
}
|
|
24584
|
-
if (await fileExists(
|
|
24972
|
+
if (await fileExists(path54.join(projectPath, "pom.xml"))) {
|
|
24585
24973
|
return { stack: "java", test: { tool: "maven", command: "mvn test" } };
|
|
24586
24974
|
}
|
|
24587
|
-
if (await fileExists(
|
|
24975
|
+
if (await fileExists(path54.join(projectPath, "gradlew")) && (await fileExists(path54.join(projectPath, "build.gradle")) || await fileExists(path54.join(projectPath, "build.gradle.kts")))) {
|
|
24588
24976
|
return { stack: "java", test: { tool: "gradle", command: "./gradlew test" } };
|
|
24589
24977
|
}
|
|
24590
24978
|
return { stack: "unknown" };
|
|
@@ -24761,7 +25149,7 @@ var init_workflow_preferences = __esm({
|
|
|
24761
25149
|
});
|
|
24762
25150
|
|
|
24763
25151
|
// core/commands/shipping.ts
|
|
24764
|
-
import
|
|
25152
|
+
import path55 from "node:path";
|
|
24765
25153
|
var ShippingCommands;
|
|
24766
25154
|
var init_shipping = __esm({
|
|
24767
25155
|
"core/commands/shipping.ts"() {
|
|
@@ -24907,7 +25295,7 @@ ${result.stderr}`.trim();
|
|
|
24907
25295
|
*/
|
|
24908
25296
|
async _bumpVersion(projectPath) {
|
|
24909
25297
|
try {
|
|
24910
|
-
const pkgPath =
|
|
25298
|
+
const pkgPath = path55.join(projectPath, "package.json");
|
|
24911
25299
|
const pkg = await file_helper_exports.readJson(pkgPath, { version: "0.0.0" });
|
|
24912
25300
|
const oldVersion = pkg?.version || "0.0.0";
|
|
24913
25301
|
const [major, minor, patch] = oldVersion.split(".").map(Number);
|
|
@@ -24929,7 +25317,7 @@ ${result.stderr}`.trim();
|
|
|
24929
25317
|
*/
|
|
24930
25318
|
async _updateChangelog(feature, version, projectPath) {
|
|
24931
25319
|
try {
|
|
24932
|
-
const changelogPath =
|
|
25320
|
+
const changelogPath = path55.join(projectPath, "CHANGELOG.md");
|
|
24933
25321
|
const changelog = await file_helper_exports.readFile(changelogPath, "# Changelog\n\n");
|
|
24934
25322
|
const entry = `## [${version}] - ${date_helper_default.formatDate(/* @__PURE__ */ new Date())}
|
|
24935
25323
|
|
|
@@ -25821,19 +26209,19 @@ var init_linear = __esm({
|
|
|
25821
26209
|
});
|
|
25822
26210
|
|
|
25823
26211
|
// core/utils/project-credentials.ts
|
|
25824
|
-
import
|
|
26212
|
+
import fs47 from "node:fs";
|
|
25825
26213
|
import os14 from "node:os";
|
|
25826
|
-
import
|
|
26214
|
+
import path56 from "node:path";
|
|
25827
26215
|
function getCredentialsPath(projectId) {
|
|
25828
|
-
return
|
|
26216
|
+
return path56.join(os14.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
|
|
25829
26217
|
}
|
|
25830
26218
|
async function getProjectCredentials(projectId) {
|
|
25831
26219
|
const credPath = getCredentialsPath(projectId);
|
|
25832
|
-
if (!
|
|
26220
|
+
if (!fs47.existsSync(credPath)) {
|
|
25833
26221
|
return {};
|
|
25834
26222
|
}
|
|
25835
26223
|
try {
|
|
25836
|
-
return JSON.parse(
|
|
26224
|
+
return JSON.parse(fs47.readFileSync(credPath, "utf-8"));
|
|
25837
26225
|
} catch (error) {
|
|
25838
26226
|
console.error("[project-credentials] Failed to read credentials:", error.message);
|
|
25839
26227
|
return {};
|
|
@@ -26410,7 +26798,7 @@ var require_package = __commonJS({
|
|
|
26410
26798
|
"package.json"(exports, module) {
|
|
26411
26799
|
module.exports = {
|
|
26412
26800
|
name: "prjct-cli",
|
|
26413
|
-
version: "0.
|
|
26801
|
+
version: "0.62.0",
|
|
26414
26802
|
description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
|
|
26415
26803
|
main: "core/index.ts",
|
|
26416
26804
|
bin: {
|
|
@@ -26517,9 +26905,9 @@ var require_package = __commonJS({
|
|
|
26517
26905
|
|
|
26518
26906
|
// core/index.ts
|
|
26519
26907
|
var core_exports = {};
|
|
26520
|
-
import
|
|
26908
|
+
import fs48 from "node:fs";
|
|
26521
26909
|
import os15 from "node:os";
|
|
26522
|
-
import
|
|
26910
|
+
import path57 from "node:path";
|
|
26523
26911
|
async function main() {
|
|
26524
26912
|
const [commandName, ...rawArgs] = process.argv.slice(2);
|
|
26525
26913
|
if (["-v", "--version", "version"].includes(commandName)) {
|
|
@@ -26651,12 +27039,12 @@ function parseCommandArgs(_cmd, rawArgs) {
|
|
|
26651
27039
|
}
|
|
26652
27040
|
function displayVersion(version) {
|
|
26653
27041
|
const detection = detectAllProviders();
|
|
26654
|
-
const claudeCommandPath =
|
|
26655
|
-
const geminiCommandPath =
|
|
26656
|
-
const claudeConfigured =
|
|
26657
|
-
const geminiConfigured =
|
|
26658
|
-
const cursorConfigured =
|
|
26659
|
-
const cursorExists =
|
|
27042
|
+
const claudeCommandPath = path57.join(os15.homedir(), ".claude", "commands", "p.md");
|
|
27043
|
+
const geminiCommandPath = path57.join(os15.homedir(), ".gemini", "commands", "p.toml");
|
|
27044
|
+
const claudeConfigured = fs48.existsSync(claudeCommandPath);
|
|
27045
|
+
const geminiConfigured = fs48.existsSync(geminiCommandPath);
|
|
27046
|
+
const cursorConfigured = fs48.existsSync(path57.join(process.cwd(), ".cursor", "commands", "sync.md"));
|
|
27047
|
+
const cursorExists = fs48.existsSync(path57.join(process.cwd(), ".cursor"));
|
|
26660
27048
|
console.log(`
|
|
26661
27049
|
${CYAN3}p/${RESET5} prjct v${version}
|
|
26662
27050
|
${DIM6}Context layer for AI coding agents${RESET5}
|
|
@@ -26789,9 +27177,9 @@ var init_core = __esm({
|
|
|
26789
27177
|
init_ai_provider();
|
|
26790
27178
|
init_config_manager();
|
|
26791
27179
|
init_editors_config();
|
|
26792
|
-
import
|
|
27180
|
+
import fs49 from "node:fs";
|
|
26793
27181
|
import os16 from "node:os";
|
|
26794
|
-
import
|
|
27182
|
+
import path58 from "node:path";
|
|
26795
27183
|
|
|
26796
27184
|
// core/server/server.ts
|
|
26797
27185
|
import { Hono as Hono3 } from "hono";
|
|
@@ -27533,14 +27921,14 @@ function checkRoutersInstalled() {
|
|
|
27533
27921
|
const home = os16.homedir();
|
|
27534
27922
|
const detection = detectAllProviders();
|
|
27535
27923
|
if (detection.claude.installed) {
|
|
27536
|
-
const claudeRouter =
|
|
27537
|
-
if (!
|
|
27924
|
+
const claudeRouter = path58.join(home, ".claude", "commands", "p.md");
|
|
27925
|
+
if (!fs49.existsSync(claudeRouter)) {
|
|
27538
27926
|
return false;
|
|
27539
27927
|
}
|
|
27540
27928
|
}
|
|
27541
27929
|
if (detection.gemini.installed) {
|
|
27542
|
-
const geminiRouter =
|
|
27543
|
-
if (!
|
|
27930
|
+
const geminiRouter = path58.join(home, ".gemini", "commands", "p.toml");
|
|
27931
|
+
if (!fs49.existsSync(geminiRouter)) {
|
|
27544
27932
|
return false;
|
|
27545
27933
|
}
|
|
27546
27934
|
}
|
|
@@ -27641,7 +28029,7 @@ if (args[0] === "start" || args[0] === "setup") {
|
|
|
27641
28029
|
console.error('No prjct project found. Run "prjct init" first.');
|
|
27642
28030
|
process.exitCode = 1;
|
|
27643
28031
|
} else {
|
|
27644
|
-
const linearCliPath =
|
|
28032
|
+
const linearCliPath = path58.join(__dirname, "..", "core", "cli", "linear.ts");
|
|
27645
28033
|
const linearArgs = ["--project", projectId, ...args.slice(1)];
|
|
27646
28034
|
const child = spawn("bun", [linearCliPath, ...linearArgs], {
|
|
27647
28035
|
stdio: "inherit",
|
|
@@ -27660,12 +28048,12 @@ if (args[0] === "start" || args[0] === "setup") {
|
|
|
27660
28048
|
const detection = detectAllProviders();
|
|
27661
28049
|
const home = os16.homedir();
|
|
27662
28050
|
const cwd = process.cwd();
|
|
27663
|
-
const claudeConfigured =
|
|
27664
|
-
const geminiConfigured =
|
|
27665
|
-
const cursorDetected =
|
|
27666
|
-
const cursorConfigured =
|
|
27667
|
-
const windsurfDetected =
|
|
27668
|
-
const windsurfConfigured =
|
|
28051
|
+
const claudeConfigured = fs49.existsSync(path58.join(home, ".claude", "commands", "p.md"));
|
|
28052
|
+
const geminiConfigured = fs49.existsSync(path58.join(home, ".gemini", "commands", "p.toml"));
|
|
28053
|
+
const cursorDetected = fs49.existsSync(path58.join(cwd, ".cursor"));
|
|
28054
|
+
const cursorConfigured = fs49.existsSync(path58.join(cwd, ".cursor", "rules", "prjct.mdc"));
|
|
28055
|
+
const windsurfDetected = fs49.existsSync(path58.join(cwd, ".windsurf"));
|
|
28056
|
+
const windsurfConfigured = fs49.existsSync(path58.join(cwd, ".windsurf", "rules", "prjct.md"));
|
|
27669
28057
|
const GREEN7 = "\x1B[32m";
|
|
27670
28058
|
console.log(`
|
|
27671
28059
|
${CYAN4}p/${RESET6} prjct v${VERSION}
|
|
@@ -27704,9 +28092,9 @@ ${DIM7}Run 'prjct init' to configure (Cursor/Windsurf IDE)${RESET6}
|
|
|
27704
28092
|
${CYAN4}https://prjct.app${RESET6}
|
|
27705
28093
|
`);
|
|
27706
28094
|
} else {
|
|
27707
|
-
const configPath =
|
|
28095
|
+
const configPath = path58.join(os16.homedir(), ".prjct-cli", "config", "installed-editors.json");
|
|
27708
28096
|
const routersInstalled = checkRoutersInstalled();
|
|
27709
|
-
if (!
|
|
28097
|
+
if (!fs49.existsSync(configPath) || !routersInstalled) {
|
|
27710
28098
|
console.log(`
|
|
27711
28099
|
${CYAN4}${BOLD4} Welcome to prjct!${RESET6}
|
|
27712
28100
|
|