@pikaa-ai/pikaa 0.3.9 → 0.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +451 -12
- package/dist/index.js +10 -0
- package/package.json +1 -1
- package/templates/base/groupy_prompt.md +4 -0
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
// src/cli/index.ts
|
|
5
5
|
import { resolve as resolve21 } from "path";
|
|
6
|
-
import { existsSync as
|
|
6
|
+
import { existsSync as existsSync21 } from "fs";
|
|
7
7
|
import { createInterface } from "readline";
|
|
8
8
|
|
|
9
9
|
// src/auth/store.ts
|
|
@@ -2680,6 +2680,16 @@ class SandboxedWorkerHost {
|
|
|
2680
2680
|
if (cleanCode.startsWith("```")) {
|
|
2681
2681
|
cleanCode = cleanCode.replace(/^```(?:javascript|js|typescript|ts)?\n?/, "").replace(/\n?```$/, "");
|
|
2682
2682
|
}
|
|
2683
|
+
cleanCode = cleanCode.replace(/import\s*\{([^}]+)\}\s*from\s*['"][^'"]+['"];?/g, (_, imported) => {
|
|
2684
|
+
return `const { ${imported} } = tools;`;
|
|
2685
|
+
});
|
|
2686
|
+
cleanCode = cleanCode.replace(/import\s*\*\s*as\s+(\w+)\s+from\s*['"][^'"]+['"];?/g, (_, varName) => {
|
|
2687
|
+
return varName === "tools" ? "" : `const ${varName} = tools;`;
|
|
2688
|
+
});
|
|
2689
|
+
cleanCode = cleanCode.replace(/import\s+(\w+)\s+from\s*['"][^'"]+['"];?/g, (_, varName) => {
|
|
2690
|
+
return varName === "tools" ? "" : `const ${varName} = tools;`;
|
|
2691
|
+
});
|
|
2692
|
+
cleanCode = cleanCode.replace(/import\s*['"][^'"]+['"];?/g, "");
|
|
2683
2693
|
const wrappedScript = `
|
|
2684
2694
|
"use strict";
|
|
2685
2695
|
const process = undefined;
|
|
@@ -6033,7 +6043,7 @@ function parsePatch(oldSrc, newSrc, contextLines = 3) {
|
|
|
6033
6043
|
// package.json
|
|
6034
6044
|
var package_default = {
|
|
6035
6045
|
name: "@pikaa-ai/pikaa",
|
|
6036
|
-
version: "0.3.
|
|
6046
|
+
version: "0.3.11",
|
|
6037
6047
|
description: "PIKAA CLI - AI coding agent that runs locally in your terminal.",
|
|
6038
6048
|
main: "./dist/index.js",
|
|
6039
6049
|
module: "./dist/index.js",
|
|
@@ -7756,9 +7766,429 @@ if (false) {}
|
|
|
7756
7766
|
var __dirname = "/home/runner/work/agent-cli/agent-cli/src/mcp/servers/sqlite";
|
|
7757
7767
|
var SQLITE_MCP_SERVER_PATH = resolve20(__dirname, "server.ts");
|
|
7758
7768
|
|
|
7769
|
+
// src/init/project-analyzer.ts
|
|
7770
|
+
import { existsSync as existsSync18, readFileSync as readFileSync13, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
|
|
7771
|
+
import { join as join9, basename as basename2 } from "path";
|
|
7772
|
+
|
|
7773
|
+
class ProjectAnalyzer {
|
|
7774
|
+
cwd;
|
|
7775
|
+
constructor(cwd = process.cwd()) {
|
|
7776
|
+
this.cwd = cwd;
|
|
7777
|
+
}
|
|
7778
|
+
analyze() {
|
|
7779
|
+
const projectName = this.detectProjectName();
|
|
7780
|
+
const languages = this.detectLanguages();
|
|
7781
|
+
const packageManager = this.detectPackageManager();
|
|
7782
|
+
const frameworks = [];
|
|
7783
|
+
const commands = {};
|
|
7784
|
+
const codeConventions = [];
|
|
7785
|
+
let description;
|
|
7786
|
+
const pkgPath = join9(this.cwd, "package.json");
|
|
7787
|
+
if (existsSync18(pkgPath)) {
|
|
7788
|
+
try {
|
|
7789
|
+
const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
|
|
7790
|
+
if (pkg.description)
|
|
7791
|
+
description = pkg.description;
|
|
7792
|
+
const pm = packageManager || "npm";
|
|
7793
|
+
const runPrefix = pm === "bun" || pm === "yarn" || pm === "pnpm" ? `${pm} run` : "npm run";
|
|
7794
|
+
const testPrefix = pm === "bun" ? "bun test" : pm === "pnpm" ? "pnpm test" : pm === "yarn" ? "yarn test" : "npm test";
|
|
7795
|
+
if (pkg.scripts) {
|
|
7796
|
+
if (pkg.scripts.build)
|
|
7797
|
+
commands.build = `${runPrefix} build`;
|
|
7798
|
+
if (pkg.scripts.test)
|
|
7799
|
+
commands.test = pkg.scripts.test === "bun test" ? "bun test" : testPrefix;
|
|
7800
|
+
if (pkg.scripts.typecheck)
|
|
7801
|
+
commands.typecheck = `${runPrefix} typecheck`;
|
|
7802
|
+
else if (pkg.scripts.check)
|
|
7803
|
+
commands.typecheck = `${runPrefix} check`;
|
|
7804
|
+
if (pkg.scripts.lint)
|
|
7805
|
+
commands.lint = `${runPrefix} lint`;
|
|
7806
|
+
if (pkg.scripts.dev)
|
|
7807
|
+
commands.dev = `${runPrefix} dev`;
|
|
7808
|
+
else if (pkg.scripts.start)
|
|
7809
|
+
commands.dev = `${runPrefix} start`;
|
|
7810
|
+
if (pkg.scripts.format)
|
|
7811
|
+
commands.format = `${runPrefix} format`;
|
|
7812
|
+
}
|
|
7813
|
+
const allDeps = {
|
|
7814
|
+
...pkg.dependencies || {},
|
|
7815
|
+
...pkg.devDependencies || {}
|
|
7816
|
+
};
|
|
7817
|
+
if (allDeps.next)
|
|
7818
|
+
frameworks.push("Next.js");
|
|
7819
|
+
if (allDeps.react)
|
|
7820
|
+
frameworks.push("React");
|
|
7821
|
+
if (allDeps.vue)
|
|
7822
|
+
frameworks.push("Vue.js");
|
|
7823
|
+
if (allDeps.svelte || allDeps["@sveltejs/kit"])
|
|
7824
|
+
frameworks.push("Svelte");
|
|
7825
|
+
if (allDeps.astro)
|
|
7826
|
+
frameworks.push("Astro");
|
|
7827
|
+
if (allDeps.express)
|
|
7828
|
+
frameworks.push("Express");
|
|
7829
|
+
if (allDeps.hono)
|
|
7830
|
+
frameworks.push("Hono");
|
|
7831
|
+
if (allDeps.fastify)
|
|
7832
|
+
frameworks.push("Fastify");
|
|
7833
|
+
if (allDeps["@nestjs/core"])
|
|
7834
|
+
frameworks.push("NestJS");
|
|
7835
|
+
if (allDeps.tailwindcss)
|
|
7836
|
+
frameworks.push("TailwindCSS");
|
|
7837
|
+
if (allDeps.vitest)
|
|
7838
|
+
frameworks.push("Vitest");
|
|
7839
|
+
if (allDeps.jest)
|
|
7840
|
+
frameworks.push("Jest");
|
|
7841
|
+
if (allDeps.playwright || allDeps["@playwright/test"])
|
|
7842
|
+
frameworks.push("Playwright");
|
|
7843
|
+
if (pkg.type === "module") {
|
|
7844
|
+
codeConventions.push('ES Modules enabled (`"type": "module"`)');
|
|
7845
|
+
} else {
|
|
7846
|
+
codeConventions.push("CommonJS module format");
|
|
7847
|
+
}
|
|
7848
|
+
} catch {}
|
|
7849
|
+
}
|
|
7850
|
+
const tsconfigPath = join9(this.cwd, "tsconfig.json");
|
|
7851
|
+
if (existsSync18(tsconfigPath)) {
|
|
7852
|
+
try {
|
|
7853
|
+
const tsconfig = JSON.parse(readFileSync13(tsconfigPath, "utf8"));
|
|
7854
|
+
if (tsconfig.compilerOptions?.strict) {
|
|
7855
|
+
codeConventions.push("TypeScript Strict Mode enabled");
|
|
7856
|
+
}
|
|
7857
|
+
if (!commands.typecheck) {
|
|
7858
|
+
commands.typecheck = "tsc --noEmit";
|
|
7859
|
+
}
|
|
7860
|
+
} catch {}
|
|
7861
|
+
}
|
|
7862
|
+
const cargoPath = join9(this.cwd, "Cargo.toml");
|
|
7863
|
+
if (existsSync18(cargoPath)) {
|
|
7864
|
+
try {
|
|
7865
|
+
const content = readFileSync13(cargoPath, "utf8");
|
|
7866
|
+
commands.build = commands.build || "cargo build";
|
|
7867
|
+
commands.test = commands.test || "cargo test";
|
|
7868
|
+
commands.lint = commands.lint || "cargo clippy";
|
|
7869
|
+
commands.dev = commands.dev || "cargo run";
|
|
7870
|
+
if (content.includes('edition = "2021"')) {
|
|
7871
|
+
codeConventions.push("Rust 2021 Edition");
|
|
7872
|
+
}
|
|
7873
|
+
if (content.includes("tokio"))
|
|
7874
|
+
frameworks.push("Tokio (Async Runtime)");
|
|
7875
|
+
if (content.includes("axum"))
|
|
7876
|
+
frameworks.push("Axum");
|
|
7877
|
+
if (content.includes("actix-web"))
|
|
7878
|
+
frameworks.push("Actix-Web");
|
|
7879
|
+
} catch {}
|
|
7880
|
+
}
|
|
7881
|
+
const goModPath = join9(this.cwd, "go.mod");
|
|
7882
|
+
if (existsSync18(goModPath)) {
|
|
7883
|
+
try {
|
|
7884
|
+
const content = readFileSync13(goModPath, "utf8");
|
|
7885
|
+
commands.build = commands.build || "go build ./...";
|
|
7886
|
+
commands.test = commands.test || "go test ./...";
|
|
7887
|
+
commands.lint = commands.lint || "golangci-lint run";
|
|
7888
|
+
commands.dev = commands.dev || "go run .";
|
|
7889
|
+
const goVer = content.match(/go\s+(\d+\.\d+)/);
|
|
7890
|
+
if (goVer?.[1]) {
|
|
7891
|
+
codeConventions.push(`Go ${goVer[1]}`);
|
|
7892
|
+
}
|
|
7893
|
+
} catch {}
|
|
7894
|
+
}
|
|
7895
|
+
const pyprojectPath = join9(this.cwd, "pyproject.toml");
|
|
7896
|
+
const requirementsPath = join9(this.cwd, "requirements.txt");
|
|
7897
|
+
if (existsSync18(pyprojectPath) || existsSync18(requirementsPath)) {
|
|
7898
|
+
commands.test = commands.test || "pytest";
|
|
7899
|
+
commands.lint = commands.lint || "ruff check .";
|
|
7900
|
+
commands.format = commands.format || "black .";
|
|
7901
|
+
if (existsSync18(join9(this.cwd, "uv.lock"))) {
|
|
7902
|
+
codeConventions.push("uv package & project manager");
|
|
7903
|
+
commands.test = "uv run pytest";
|
|
7904
|
+
} else if (existsSync18(join9(this.cwd, "poetry.lock"))) {
|
|
7905
|
+
codeConventions.push("Poetry dependency manager");
|
|
7906
|
+
commands.test = "poetry run pytest";
|
|
7907
|
+
}
|
|
7908
|
+
}
|
|
7909
|
+
const directoryStructure = this.scanDirectoryStructure();
|
|
7910
|
+
const instructionFiles = ["AGENTS.md", "CLAUDE.md", ".agents.md", "AGENTS.override.md"];
|
|
7911
|
+
let hasExistingInstructions = false;
|
|
7912
|
+
let existingInstructionFile;
|
|
7913
|
+
for (const f of instructionFiles) {
|
|
7914
|
+
if (existsSync18(join9(this.cwd, f))) {
|
|
7915
|
+
hasExistingInstructions = true;
|
|
7916
|
+
existingInstructionFile = f;
|
|
7917
|
+
break;
|
|
7918
|
+
}
|
|
7919
|
+
}
|
|
7920
|
+
return {
|
|
7921
|
+
projectName,
|
|
7922
|
+
description,
|
|
7923
|
+
languages,
|
|
7924
|
+
packageManager,
|
|
7925
|
+
frameworks,
|
|
7926
|
+
commands,
|
|
7927
|
+
directoryStructure,
|
|
7928
|
+
codeConventions,
|
|
7929
|
+
hasExistingInstructions,
|
|
7930
|
+
existingInstructionFile
|
|
7931
|
+
};
|
|
7932
|
+
}
|
|
7933
|
+
generateAgentsMarkdown(analysis) {
|
|
7934
|
+
const lines = [];
|
|
7935
|
+
lines.push(`# ${analysis.projectName}`);
|
|
7936
|
+
lines.push("");
|
|
7937
|
+
if (analysis.description) {
|
|
7938
|
+
lines.push(`> ${analysis.description}`);
|
|
7939
|
+
lines.push("");
|
|
7940
|
+
}
|
|
7941
|
+
lines.push("## Tech Stack");
|
|
7942
|
+
lines.push("");
|
|
7943
|
+
if (analysis.languages.length > 0) {
|
|
7944
|
+
lines.push(`- **Languages**: ${analysis.languages.join(", ")}`);
|
|
7945
|
+
}
|
|
7946
|
+
if (analysis.packageManager) {
|
|
7947
|
+
lines.push(`- **Package Manager**: ${analysis.packageManager}`);
|
|
7948
|
+
}
|
|
7949
|
+
if (analysis.frameworks.length > 0) {
|
|
7950
|
+
lines.push(`- **Frameworks & Libraries**: ${analysis.frameworks.join(", ")}`);
|
|
7951
|
+
}
|
|
7952
|
+
lines.push("");
|
|
7953
|
+
lines.push("## Development Commands");
|
|
7954
|
+
lines.push("");
|
|
7955
|
+
if (Object.keys(analysis.commands).length > 0) {
|
|
7956
|
+
if (analysis.commands.build)
|
|
7957
|
+
lines.push(`- **Build**: \`${analysis.commands.build}\``);
|
|
7958
|
+
if (analysis.commands.test)
|
|
7959
|
+
lines.push(`- **Test**: \`${analysis.commands.test}\``);
|
|
7960
|
+
if (analysis.commands.typecheck)
|
|
7961
|
+
lines.push(`- **Typecheck**: \`${analysis.commands.typecheck}\``);
|
|
7962
|
+
if (analysis.commands.lint)
|
|
7963
|
+
lines.push(`- **Lint**: \`${analysis.commands.lint}\``);
|
|
7964
|
+
if (analysis.commands.dev)
|
|
7965
|
+
lines.push(`- **Dev / Run**: \`${analysis.commands.dev}\``);
|
|
7966
|
+
if (analysis.commands.format)
|
|
7967
|
+
lines.push(`- **Format**: \`${analysis.commands.format}\``);
|
|
7968
|
+
} else {
|
|
7969
|
+
lines.push("- *No standard build/test commands detected.*");
|
|
7970
|
+
}
|
|
7971
|
+
lines.push("");
|
|
7972
|
+
lines.push("## Architecture & Directory Structure");
|
|
7973
|
+
lines.push("");
|
|
7974
|
+
if (Object.keys(analysis.directoryStructure).length > 0) {
|
|
7975
|
+
for (const [dir, purpose] of Object.entries(analysis.directoryStructure)) {
|
|
7976
|
+
lines.push(`- \`${dir}\`: ${purpose}`);
|
|
7977
|
+
}
|
|
7978
|
+
} else {
|
|
7979
|
+
lines.push("- Root project workspace");
|
|
7980
|
+
}
|
|
7981
|
+
lines.push("");
|
|
7982
|
+
lines.push("## Code Style & Guidelines");
|
|
7983
|
+
lines.push("");
|
|
7984
|
+
if (analysis.codeConventions.length > 0) {
|
|
7985
|
+
for (const conv of analysis.codeConventions) {
|
|
7986
|
+
lines.push(`- ${conv}`);
|
|
7987
|
+
}
|
|
7988
|
+
}
|
|
7989
|
+
lines.push("- Keep functions focused and modular.");
|
|
7990
|
+
lines.push("- Maintain clean error handling and avoid unhandled exceptions.");
|
|
7991
|
+
lines.push("- Run automated test suite before completing major code changes.");
|
|
7992
|
+
lines.push("");
|
|
7993
|
+
return lines.join(`
|
|
7994
|
+
`);
|
|
7995
|
+
}
|
|
7996
|
+
detectProjectName() {
|
|
7997
|
+
const pkgPath = join9(this.cwd, "package.json");
|
|
7998
|
+
if (existsSync18(pkgPath)) {
|
|
7999
|
+
try {
|
|
8000
|
+
const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
|
|
8001
|
+
if (pkg.name) {
|
|
8002
|
+
return pkg.name.startsWith("@") ? pkg.name.split("/")[1] || pkg.name : pkg.name;
|
|
8003
|
+
}
|
|
8004
|
+
} catch {}
|
|
8005
|
+
}
|
|
8006
|
+
const cargoPath = join9(this.cwd, "Cargo.toml");
|
|
8007
|
+
if (existsSync18(cargoPath)) {
|
|
8008
|
+
try {
|
|
8009
|
+
const match = readFileSync13(cargoPath, "utf8").match(/name\s*=\s*"([^"]+)"/);
|
|
8010
|
+
if (match?.[1])
|
|
8011
|
+
return match[1];
|
|
8012
|
+
} catch {}
|
|
8013
|
+
}
|
|
8014
|
+
const goModPath = join9(this.cwd, "go.mod");
|
|
8015
|
+
if (existsSync18(goModPath)) {
|
|
8016
|
+
try {
|
|
8017
|
+
const match = readFileSync13(goModPath, "utf8").match(/module\s+([^\s]+)/);
|
|
8018
|
+
if (match?.[1])
|
|
8019
|
+
return basename2(match[1]);
|
|
8020
|
+
} catch {}
|
|
8021
|
+
}
|
|
8022
|
+
return basename2(this.cwd);
|
|
8023
|
+
}
|
|
8024
|
+
detectLanguages() {
|
|
8025
|
+
const langs = new Set;
|
|
8026
|
+
if (existsSync18(join9(this.cwd, "tsconfig.json")) || this.hasFileWithExtension(".ts", ".tsx")) {
|
|
8027
|
+
langs.add("TypeScript");
|
|
8028
|
+
}
|
|
8029
|
+
if (existsSync18(join9(this.cwd, "package.json")) || this.hasFileWithExtension(".js", ".jsx", ".mjs")) {
|
|
8030
|
+
langs.add("JavaScript");
|
|
8031
|
+
}
|
|
8032
|
+
if (existsSync18(join9(this.cwd, "Cargo.toml")) || this.hasFileWithExtension(".rs")) {
|
|
8033
|
+
langs.add("Rust");
|
|
8034
|
+
}
|
|
8035
|
+
if (existsSync18(join9(this.cwd, "go.mod")) || this.hasFileWithExtension(".go")) {
|
|
8036
|
+
langs.add("Go");
|
|
8037
|
+
}
|
|
8038
|
+
if (existsSync18(join9(this.cwd, "pyproject.toml")) || existsSync18(join9(this.cwd, "requirements.txt")) || this.hasFileWithExtension(".py")) {
|
|
8039
|
+
langs.add("Python");
|
|
8040
|
+
}
|
|
8041
|
+
if (existsSync18(join9(this.cwd, "pom.xml")) || existsSync18(join9(this.cwd, "build.gradle")) || this.hasFileWithExtension(".java")) {
|
|
8042
|
+
langs.add("Java");
|
|
8043
|
+
}
|
|
8044
|
+
if (existsSync18(join9(this.cwd, "CMakeLists.txt")) || this.hasFileWithExtension(".cpp", ".c", ".h", ".hpp")) {
|
|
8045
|
+
langs.add("C/C++");
|
|
8046
|
+
}
|
|
8047
|
+
return Array.from(langs);
|
|
8048
|
+
}
|
|
8049
|
+
detectPackageManager() {
|
|
8050
|
+
if (existsSync18(join9(this.cwd, "bun.lockb")) || existsSync18(join9(this.cwd, "bun.lock")))
|
|
8051
|
+
return "bun";
|
|
8052
|
+
if (existsSync18(join9(this.cwd, "pnpm-lock.yaml")))
|
|
8053
|
+
return "pnpm";
|
|
8054
|
+
if (existsSync18(join9(this.cwd, "yarn.lock")))
|
|
8055
|
+
return "yarn";
|
|
8056
|
+
if (existsSync18(join9(this.cwd, "package-lock.json")))
|
|
8057
|
+
return "npm";
|
|
8058
|
+
if (existsSync18(join9(this.cwd, "Cargo.lock")) || existsSync18(join9(this.cwd, "Cargo.toml")))
|
|
8059
|
+
return "cargo";
|
|
8060
|
+
if (existsSync18(join9(this.cwd, "uv.lock")))
|
|
8061
|
+
return "uv";
|
|
8062
|
+
if (existsSync18(join9(this.cwd, "poetry.lock")))
|
|
8063
|
+
return "poetry";
|
|
8064
|
+
if (existsSync18(join9(this.cwd, "go.sum")) || existsSync18(join9(this.cwd, "go.mod")))
|
|
8065
|
+
return "go";
|
|
8066
|
+
if (existsSync18(join9(this.cwd, "package.json")))
|
|
8067
|
+
return "npm";
|
|
8068
|
+
return;
|
|
8069
|
+
}
|
|
8070
|
+
scanDirectoryStructure() {
|
|
8071
|
+
const structure = {};
|
|
8072
|
+
const commonDirPurposes = {
|
|
8073
|
+
src: "Core application source code and business logic",
|
|
8074
|
+
lib: "Shared libraries, utilities, and helper modules",
|
|
8075
|
+
tests: "Automated unit and integration test suites",
|
|
8076
|
+
test: "Automated test suite",
|
|
8077
|
+
dist: "Compiled production distribution output",
|
|
8078
|
+
build: "Compiled build artifacts",
|
|
8079
|
+
docs: "Documentation and architectural specifications",
|
|
8080
|
+
pkg: "Reusable public Go/Rust/JS packages",
|
|
8081
|
+
cmd: "Main application CLI commands and entry points",
|
|
8082
|
+
bin: "CLI executable launcher scripts and binaries",
|
|
8083
|
+
templates: "Prompt and code generator templates",
|
|
8084
|
+
components: "Reusable UI components",
|
|
8085
|
+
app: "Application pages and routing handlers",
|
|
8086
|
+
pages: "Page views and route controllers",
|
|
8087
|
+
api: "Backend API endpoints and server routes",
|
|
8088
|
+
public: "Static public assets and web resources",
|
|
8089
|
+
assets: "Media assets, icons, and graphic resources",
|
|
8090
|
+
scripts: "Build automation, CI helpers, and deployment scripts",
|
|
8091
|
+
config: "Application configuration files",
|
|
8092
|
+
storage: "Local databases, caches, and persistent state files"
|
|
8093
|
+
};
|
|
8094
|
+
try {
|
|
8095
|
+
const entries = readdirSync6(this.cwd);
|
|
8096
|
+
for (const entry of entries) {
|
|
8097
|
+
if (entry.startsWith(".") || entry === "node_modules" || entry === "target")
|
|
8098
|
+
continue;
|
|
8099
|
+
const fullPath = join9(this.cwd, entry);
|
|
8100
|
+
try {
|
|
8101
|
+
if (statSync4(fullPath).isDirectory()) {
|
|
8102
|
+
const purpose = commonDirPurposes[entry.toLowerCase()] || `Directory for ${entry} modules`;
|
|
8103
|
+
structure[`${entry}/`] = purpose;
|
|
8104
|
+
}
|
|
8105
|
+
} catch {}
|
|
8106
|
+
}
|
|
8107
|
+
} catch {}
|
|
8108
|
+
return structure;
|
|
8109
|
+
}
|
|
8110
|
+
hasFileWithExtension(...exts) {
|
|
8111
|
+
try {
|
|
8112
|
+
const entries = readdirSync6(this.cwd);
|
|
8113
|
+
return entries.some((e) => exts.some((ext) => e.endsWith(ext)));
|
|
8114
|
+
} catch {
|
|
8115
|
+
return false;
|
|
8116
|
+
}
|
|
8117
|
+
}
|
|
8118
|
+
}
|
|
8119
|
+
// src/init/init-command.ts
|
|
8120
|
+
import { existsSync as existsSync19, writeFileSync as writeFileSync7 } from "fs";
|
|
8121
|
+
import { join as join10 } from "path";
|
|
8122
|
+
function runProjectInit(options = {}) {
|
|
8123
|
+
const cwd = options.cwd || process.cwd();
|
|
8124
|
+
const filename = options.filename || "AGENTS.md";
|
|
8125
|
+
const targetPath = join10(cwd, filename);
|
|
8126
|
+
const analyzer = new ProjectAnalyzer(cwd);
|
|
8127
|
+
const analysis = analyzer.analyze();
|
|
8128
|
+
const content = analyzer.generateAgentsMarkdown(analysis);
|
|
8129
|
+
const alreadyExists = existsSync19(targetPath);
|
|
8130
|
+
writeFileSync7(targetPath, content, "utf8");
|
|
8131
|
+
return {
|
|
8132
|
+
success: true,
|
|
8133
|
+
filePath: targetPath,
|
|
8134
|
+
analysis,
|
|
8135
|
+
content,
|
|
8136
|
+
overwritten: alreadyExists
|
|
8137
|
+
};
|
|
8138
|
+
}
|
|
8139
|
+
function printInitSummary(result) {
|
|
8140
|
+
const BOLD2 = "\x1B[1m";
|
|
8141
|
+
const GREEN = "\x1B[38;2;120;220;140m";
|
|
8142
|
+
const BRAND = "\x1B[38;2;217;119;87m";
|
|
8143
|
+
const CYAN = "\x1B[38;2;125;207;255m";
|
|
8144
|
+
const GRAY2 = "\x1B[38;2;148;148;148m";
|
|
8145
|
+
const WHITE2 = "\x1B[38;2;240;240;245m";
|
|
8146
|
+
const RESET2 = "\x1B[0m";
|
|
8147
|
+
const { analysis, filePath, overwritten } = result;
|
|
8148
|
+
console.log("");
|
|
8149
|
+
console.log(` ${GREEN}\u2713${RESET2} ${BOLD2}${WHITE2}${overwritten ? "Updated" : "Created"} Project Instructions Document${RESET2}`);
|
|
8150
|
+
console.log(` ${GRAY2}Path: ${CYAN}${filePath}${RESET2}`);
|
|
8151
|
+
console.log("");
|
|
8152
|
+
console.log(` ${BRAND}\u250C\u2500 ${BOLD2}Project Overview${RESET2} ${BRAND}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510${RESET2}`);
|
|
8153
|
+
console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Project:${RESET2} ${WHITE2}${analysis.projectName}${RESET2}`);
|
|
8154
|
+
if (analysis.languages.length > 0) {
|
|
8155
|
+
console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Languages:${RESET2} ${analysis.languages.join(", ")}`);
|
|
8156
|
+
}
|
|
8157
|
+
if (analysis.packageManager) {
|
|
8158
|
+
console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Package Manager:${RESET2} ${analysis.packageManager}`);
|
|
8159
|
+
}
|
|
8160
|
+
if (analysis.frameworks.length > 0) {
|
|
8161
|
+
console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Frameworks:${RESET2} ${analysis.frameworks.join(", ")}`);
|
|
8162
|
+
}
|
|
8163
|
+
console.log(` ${BRAND}\u2502${RESET2}`);
|
|
8164
|
+
console.log(` ${BRAND}\u2502${RESET2} ${BOLD2}Detected Commands:${RESET2}`);
|
|
8165
|
+
if (analysis.commands.build) {
|
|
8166
|
+
console.log(` ${BRAND}\u2502${RESET2} \u2022 Build: ${CYAN}${analysis.commands.build}${RESET2}`);
|
|
8167
|
+
}
|
|
8168
|
+
if (analysis.commands.test) {
|
|
8169
|
+
console.log(` ${BRAND}\u2502${RESET2} \u2022 Test: ${GREEN}${analysis.commands.test}${RESET2}`);
|
|
8170
|
+
}
|
|
8171
|
+
if (analysis.commands.typecheck) {
|
|
8172
|
+
console.log(` ${BRAND}\u2502${RESET2} \u2022 Typecheck: ${CYAN}${analysis.commands.typecheck}${RESET2}`);
|
|
8173
|
+
}
|
|
8174
|
+
if (analysis.commands.lint) {
|
|
8175
|
+
console.log(` ${BRAND}\u2502${RESET2} \u2022 Lint: ${CYAN}${analysis.commands.lint}${RESET2}`);
|
|
8176
|
+
}
|
|
8177
|
+
if (analysis.commands.dev) {
|
|
8178
|
+
console.log(` ${BRAND}\u2502${RESET2} \u2022 Dev: ${CYAN}${analysis.commands.dev}${RESET2}`);
|
|
8179
|
+
}
|
|
8180
|
+
if (Object.keys(analysis.commands).length === 0) {
|
|
8181
|
+
console.log(` ${BRAND}\u2502${RESET2} \u2022 ${GRAY2}(No standard commands detected)${RESET2}`);
|
|
8182
|
+
}
|
|
8183
|
+
console.log(` ${BRAND}\u2502${RESET2}`);
|
|
8184
|
+
console.log(` ${BRAND}\u2502${RESET2} ${GRAY2}AI agents will now automatically load AGENTS.md on every session.${RESET2}`);
|
|
8185
|
+
console.log(` ${BRAND}\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518${RESET2}`);
|
|
8186
|
+
console.log("");
|
|
8187
|
+
}
|
|
7759
8188
|
// src/cli/commands.ts
|
|
7760
8189
|
var AVAILABLE_SLASH_COMMANDS = [
|
|
7761
8190
|
{ name: "/help", description: "Show command list and help menu" },
|
|
8191
|
+
{ name: "/init", description: "Initialize or update AGENTS.md project instructions" },
|
|
7762
8192
|
{ name: "/stats", description: "Display session runtime, turn stats & sub-agent status" },
|
|
7763
8193
|
{ name: "/model", description: "Select or switch active AI model" },
|
|
7764
8194
|
{ name: "/reasoning", description: "Toggle internal reasoning chain visibility" },
|
|
@@ -7851,6 +8281,10 @@ async function handleSlashCommand(input, ctx) {
|
|
|
7851
8281
|
\x1B[38;2;95;175;175m\u23F8 Switched to Plan Mode (read-only planning, mutations blocked)\x1B[0m
|
|
7852
8282
|
`);
|
|
7853
8283
|
return true;
|
|
8284
|
+
case "/init":
|
|
8285
|
+
const initResult = runProjectInit({ cwd: ctx.session.cwd });
|
|
8286
|
+
printInitSummary(initResult);
|
|
8287
|
+
return true;
|
|
7854
8288
|
case "/agents":
|
|
7855
8289
|
printAgents(ctx);
|
|
7856
8290
|
return true;
|
|
@@ -9116,9 +9550,9 @@ class MarkdownHighlighter {
|
|
|
9116
9550
|
}
|
|
9117
9551
|
|
|
9118
9552
|
// src/cli/update-checker.ts
|
|
9119
|
-
import { existsSync as
|
|
9553
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "fs";
|
|
9120
9554
|
import { homedir as homedir9 } from "os";
|
|
9121
|
-
import { join as
|
|
9555
|
+
import { join as join11 } from "path";
|
|
9122
9556
|
var CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;
|
|
9123
9557
|
function parseSemver(v) {
|
|
9124
9558
|
const clean = v.replace(/^v/, "").trim();
|
|
@@ -9139,8 +9573,8 @@ function isNewerVersion(current, remote) {
|
|
|
9139
9573
|
return remPatch > curPatch;
|
|
9140
9574
|
}
|
|
9141
9575
|
function getUpdateCachePath() {
|
|
9142
|
-
const baseDir = process.env.PIKAA_HOME || process.env.GROUPY_HOME ||
|
|
9143
|
-
return
|
|
9576
|
+
const baseDir = process.env.PIKAA_HOME || process.env.GROUPY_HOME || join11(homedir9(), ".pikaa");
|
|
9577
|
+
return join11(baseDir, "update-cache.json");
|
|
9144
9578
|
}
|
|
9145
9579
|
async function fetchLatestNpmVersion(packageName, timeoutMs = 1500) {
|
|
9146
9580
|
const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`;
|
|
@@ -9173,9 +9607,9 @@ async function checkForUpdates(options = {}) {
|
|
|
9173
9607
|
const cachePath = options.cachePath || getUpdateCachePath();
|
|
9174
9608
|
const now = Date.now();
|
|
9175
9609
|
let cached = null;
|
|
9176
|
-
if (!options.force &&
|
|
9610
|
+
if (!options.force && existsSync20(cachePath)) {
|
|
9177
9611
|
try {
|
|
9178
|
-
const raw = JSON.parse(
|
|
9612
|
+
const raw = JSON.parse(readFileSync14(cachePath, "utf8"));
|
|
9179
9613
|
if (raw && typeof raw.lastChecked === "number" && typeof raw.latestVersion === "string") {
|
|
9180
9614
|
cached = raw;
|
|
9181
9615
|
if (now - cached.lastChecked < CHECK_INTERVAL_MS) {
|
|
@@ -9203,8 +9637,8 @@ async function checkForUpdates(options = {}) {
|
|
|
9203
9637
|
return null;
|
|
9204
9638
|
}
|
|
9205
9639
|
try {
|
|
9206
|
-
const parentDir =
|
|
9207
|
-
if (!
|
|
9640
|
+
const parentDir = join11(cachePath, "..");
|
|
9641
|
+
if (!existsSync20(parentDir)) {
|
|
9208
9642
|
mkdirSync10(parentDir, { recursive: true });
|
|
9209
9643
|
}
|
|
9210
9644
|
const cacheData = {
|
|
@@ -9212,7 +9646,7 @@ async function checkForUpdates(options = {}) {
|
|
|
9212
9646
|
latestVersion,
|
|
9213
9647
|
packageName
|
|
9214
9648
|
};
|
|
9215
|
-
|
|
9649
|
+
writeFileSync8(cachePath, JSON.stringify(cacheData, null, 2), "utf8");
|
|
9216
9650
|
} catch {}
|
|
9217
9651
|
const updateAvailable = isNewerVersion(currentVersion, latestVersion);
|
|
9218
9652
|
return updateAvailable ? {
|
|
@@ -9579,6 +10013,10 @@ async function main() {
|
|
|
9579
10013
|
} else if (arg === "worktrees" || arg === "worktree") {
|
|
9580
10014
|
await printWorktreesList(worktreeManager, cwd);
|
|
9581
10015
|
process.exit(0);
|
|
10016
|
+
} else if (arg === "init") {
|
|
10017
|
+
const initResult = runProjectInit({ cwd });
|
|
10018
|
+
printInitSummary(initResult);
|
|
10019
|
+
process.exit(0);
|
|
9582
10020
|
} else if (arg === "--resume" || arg === "-R" || arg === "resume") {
|
|
9583
10021
|
resumeThreadId = args[++i];
|
|
9584
10022
|
} else if (arg === "--model" || arg === "-m") {
|
|
@@ -9620,7 +10058,7 @@ async function main() {
|
|
|
9620
10058
|
resolve21(cwd, "mcp_config.json")
|
|
9621
10059
|
].filter(Boolean);
|
|
9622
10060
|
for (const cfg of candidateConfigs) {
|
|
9623
|
-
if (
|
|
10061
|
+
if (existsSync21(cfg)) {
|
|
9624
10062
|
try {
|
|
9625
10063
|
await mcpManager.loadConfigFile(cfg);
|
|
9626
10064
|
mcpManager.registerToolsIntoRouter(tools4);
|
|
@@ -9878,6 +10316,7 @@ ${style.bold("USAGE:")}
|
|
|
9878
10316
|
groupy skills # List available domain skills
|
|
9879
10317
|
groupy memories # View learned user preferences
|
|
9880
10318
|
groupy worktrees # List active isolated Git Worktrees
|
|
10319
|
+
groupy init # Initialize or update AGENTS.md project instructions
|
|
9881
10320
|
|
|
9882
10321
|
${style.bold("OPTIONS:")}
|
|
9883
10322
|
-R, --resume <id> Resume an existing session from SQLite storage
|
package/dist/index.js
CHANGED
|
@@ -2935,6 +2935,16 @@ class SandboxedWorkerHost {
|
|
|
2935
2935
|
if (cleanCode.startsWith("```")) {
|
|
2936
2936
|
cleanCode = cleanCode.replace(/^```(?:javascript|js|typescript|ts)?\n?/, "").replace(/\n?```$/, "");
|
|
2937
2937
|
}
|
|
2938
|
+
cleanCode = cleanCode.replace(/import\s*\{([^}]+)\}\s*from\s*['"][^'"]+['"];?/g, (_, imported) => {
|
|
2939
|
+
return `const { ${imported} } = tools;`;
|
|
2940
|
+
});
|
|
2941
|
+
cleanCode = cleanCode.replace(/import\s*\*\s*as\s+(\w+)\s+from\s*['"][^'"]+['"];?/g, (_, varName) => {
|
|
2942
|
+
return varName === "tools" ? "" : `const ${varName} = tools;`;
|
|
2943
|
+
});
|
|
2944
|
+
cleanCode = cleanCode.replace(/import\s+(\w+)\s+from\s*['"][^'"]+['"];?/g, (_, varName) => {
|
|
2945
|
+
return varName === "tools" ? "" : `const ${varName} = tools;`;
|
|
2946
|
+
});
|
|
2947
|
+
cleanCode = cleanCode.replace(/import\s*['"][^'"]+['"];?/g, "");
|
|
2938
2948
|
const wrappedScript = `
|
|
2939
2949
|
"use strict";
|
|
2940
2950
|
const process = undefined;
|
package/package.json
CHANGED
|
@@ -47,6 +47,10 @@ You are Groupy, an expert autonomous AI coding assistant. You are running as a c
|
|
|
47
47
|
|
|
48
48
|
## Codebase Discovery & Execution Strategy
|
|
49
49
|
|
|
50
|
+
0. **Project Instructions Precedence (`AGENTS.md` / `CLAUDE.md`)**:
|
|
51
|
+
- If `AGENTS.md`, `CLAUDE.md`, or `.agents.md` is present in the workspace, its instructions take immediate precedence.
|
|
52
|
+
- Always prioritize and follow the development commands (build, test, lint), architectural constraints, and code conventions defined in `AGENTS.md` before executing any commands.
|
|
53
|
+
|
|
50
54
|
1. **Broad Exploration ("pelajari project ini / repo ini tentang apa")**:
|
|
51
55
|
- Inspect ONLY root configs (`package.json`, `Cargo.toml`, `go.mod`, `pyproject.toml`, etc.), `README.md`, and top-level directory tree.
|
|
52
56
|
- Deliver a concise Architecture Overview (Tech stack, folder hierarchy, main entry points).
|