lynxprompt 1.2.10 → 1.2.12
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/index.js +262 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1549,6 +1549,7 @@ async function detectProject(cwd) {
|
|
|
1549
1549
|
const detected = {
|
|
1550
1550
|
name: null,
|
|
1551
1551
|
stack: [],
|
|
1552
|
+
databases: [],
|
|
1552
1553
|
commands: {},
|
|
1553
1554
|
packageManager: null,
|
|
1554
1555
|
type: "unknown"
|
|
@@ -1879,6 +1880,8 @@ function parseGitLabUrl(url) {
|
|
|
1879
1880
|
}
|
|
1880
1881
|
return null;
|
|
1881
1882
|
}
|
|
1883
|
+
var OPEN_SOURCE_LICENSES = ["mit", "apache-2.0", "gpl-3.0", "lgpl-3.0", "agpl-3.0", "bsd-2-clause", "bsd-3-clause", "mpl-2.0", "unlicense", "cc0-1.0", "isc"];
|
|
1884
|
+
var STATIC_FILES = [".editorconfig", "CONTRIBUTING.md", "CODE_OF_CONDUCT.md", "SECURITY.md", "ROADMAP.md", ".gitignore", "LICENSE", "README.md", "ARCHITECTURE.md", "CHANGELOG.md"];
|
|
1882
1885
|
async function detectFromGitHubApi(repoUrl) {
|
|
1883
1886
|
const parsed = parseGitHubUrl(repoUrl);
|
|
1884
1887
|
if (!parsed) return null;
|
|
@@ -1890,17 +1893,24 @@ async function detectFromGitHubApi(repoUrl) {
|
|
|
1890
1893
|
if (!repoRes.ok) return null;
|
|
1891
1894
|
const repoInfo = await repoRes.json();
|
|
1892
1895
|
if (repoInfo.private) return null;
|
|
1896
|
+
const licenseId = repoInfo.license?.spdx_id?.toLowerCase() || null;
|
|
1897
|
+
const isOpenSource = !repoInfo.private && (licenseId ? OPEN_SOURCE_LICENSES.includes(licenseId) : false);
|
|
1893
1898
|
const detected = {
|
|
1894
1899
|
name: repoInfo.name,
|
|
1895
1900
|
description: repoInfo.description ?? void 0,
|
|
1896
1901
|
stack: [],
|
|
1902
|
+
databases: [],
|
|
1897
1903
|
commands: {},
|
|
1898
1904
|
packageManager: null,
|
|
1899
1905
|
type: "application",
|
|
1900
1906
|
repoHost: "github",
|
|
1901
1907
|
repoUrl,
|
|
1902
|
-
license:
|
|
1903
|
-
isPublicRepo: !repoInfo.private
|
|
1908
|
+
license: licenseId ?? void 0,
|
|
1909
|
+
isPublicRepo: !repoInfo.private,
|
|
1910
|
+
isOpenSource,
|
|
1911
|
+
projectType: isOpenSource ? "open_source" : void 0,
|
|
1912
|
+
hasDocker: false,
|
|
1913
|
+
existingFiles: []
|
|
1904
1914
|
};
|
|
1905
1915
|
const filesRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/`, {
|
|
1906
1916
|
headers: { "User-Agent": "LynxPrompt-CLI" }
|
|
@@ -1908,32 +1918,108 @@ async function detectFromGitHubApi(repoUrl) {
|
|
|
1908
1918
|
if (!filesRes.ok) return detected;
|
|
1909
1919
|
const files = await filesRes.json();
|
|
1910
1920
|
const fileNames = new Set(files.map((f) => f.name.toLowerCase()));
|
|
1921
|
+
for (const file of STATIC_FILES) {
|
|
1922
|
+
if (files.some((f) => f.name.toLowerCase() === file.toLowerCase())) {
|
|
1923
|
+
detected.existingFiles.push(file);
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
if (fileNames.has("dockerfile") || fileNames.has("docker-compose.yml") || fileNames.has("docker-compose.yaml")) {
|
|
1927
|
+
detected.hasDocker = true;
|
|
1928
|
+
detected.stack.push("docker");
|
|
1929
|
+
const dockerComposeFile = fileNames.has("docker-compose.yml") ? "docker-compose.yml" : fileNames.has("docker-compose.yaml") ? "docker-compose.yaml" : null;
|
|
1930
|
+
if (dockerComposeFile) {
|
|
1931
|
+
const composeRes = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/HEAD/${dockerComposeFile}`);
|
|
1932
|
+
if (composeRes.ok) {
|
|
1933
|
+
try {
|
|
1934
|
+
const content = await composeRes.text();
|
|
1935
|
+
const lowerContent = content.toLowerCase();
|
|
1936
|
+
if (content.includes("ghcr.io")) detected.containerRegistry = "ghcr";
|
|
1937
|
+
else if (content.includes("docker.io") || /image:\s*[a-z0-9]+\/[a-z0-9]/.test(content)) detected.containerRegistry = "dockerhub";
|
|
1938
|
+
else if (content.includes("gcr.io")) detected.containerRegistry = "gcr";
|
|
1939
|
+
else if (content.includes("ecr.") || content.includes(".amazonaws.com")) detected.containerRegistry = "ecr";
|
|
1940
|
+
else if (content.includes("azurecr.io")) detected.containerRegistry = "acr";
|
|
1941
|
+
else if (content.includes("quay.io")) detected.containerRegistry = "quay";
|
|
1942
|
+
else if (content.includes("registry.gitlab.com")) detected.containerRegistry = "gitlab_registry";
|
|
1943
|
+
if (lowerContent.includes("postgres")) detected.databases.push("postgresql");
|
|
1944
|
+
if (lowerContent.includes("mysql") && !lowerContent.includes("mysql-")) detected.databases.push("mysql");
|
|
1945
|
+
if (lowerContent.includes("mongo")) detected.databases.push("mongodb");
|
|
1946
|
+
if (lowerContent.includes("redis")) detected.databases.push("redis");
|
|
1947
|
+
if (lowerContent.includes("sqlite")) detected.databases.push("sqlite");
|
|
1948
|
+
if (lowerContent.includes("mariadb")) detected.databases.push("mariadb");
|
|
1949
|
+
} catch {
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
if (files.some((f) => f.name === ".github" && f.type === "dir")) {
|
|
1955
|
+
const ghFilesRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/.github`, {
|
|
1956
|
+
headers: { "User-Agent": "LynxPrompt-CLI" }
|
|
1957
|
+
});
|
|
1958
|
+
if (ghFilesRes.ok) {
|
|
1959
|
+
const ghFiles = await ghFilesRes.json();
|
|
1960
|
+
if (ghFiles.some((f) => f.name === "workflows")) {
|
|
1961
|
+
detected.cicd = "github_actions";
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
if (fileNames.has(".gitlab-ci.yml")) detected.cicd = "gitlab_ci";
|
|
1966
|
+
if (fileNames.has("jenkinsfile")) detected.cicd = "jenkins";
|
|
1967
|
+
if (fileNames.has(".travis.yml")) detected.cicd = "travis";
|
|
1968
|
+
if (fileNames.has("azure-pipelines.yml")) detected.cicd = "azure_devops";
|
|
1911
1969
|
if (fileNames.has("pyproject.toml")) {
|
|
1912
1970
|
detected.stack.push("python");
|
|
1913
1971
|
const pyprojectRes = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/HEAD/pyproject.toml`);
|
|
1914
1972
|
if (pyprojectRes.ok) {
|
|
1915
1973
|
try {
|
|
1916
1974
|
const content = await pyprojectRes.text();
|
|
1917
|
-
|
|
1918
|
-
if (
|
|
1919
|
-
if (
|
|
1920
|
-
if (
|
|
1921
|
-
if (
|
|
1922
|
-
if (
|
|
1923
|
-
if (
|
|
1975
|
+
const lowerContent = content.toLowerCase();
|
|
1976
|
+
if (lowerContent.includes("fastapi")) detected.stack.push("fastapi");
|
|
1977
|
+
if (lowerContent.includes("django")) detected.stack.push("django");
|
|
1978
|
+
if (lowerContent.includes("flask")) detected.stack.push("flask");
|
|
1979
|
+
if (lowerContent.includes("sqlalchemy")) detected.stack.push("sqlalchemy");
|
|
1980
|
+
if (lowerContent.includes("pydantic")) detected.stack.push("pydantic");
|
|
1981
|
+
if (lowerContent.includes("pytest")) detected.testFramework = "pytest";
|
|
1982
|
+
else if (lowerContent.includes("unittest")) detected.testFramework = "unittest";
|
|
1983
|
+
detected.commands.test = "pytest";
|
|
1984
|
+
if (lowerContent.includes("ruff")) detected.commands.lint = "ruff check .";
|
|
1985
|
+
if (lowerContent.includes("asyncpg") || lowerContent.includes("psycopg")) {
|
|
1986
|
+
if (!detected.databases.includes("postgresql")) detected.databases.push("postgresql");
|
|
1987
|
+
}
|
|
1988
|
+
if (lowerContent.includes("aiosqlite") || lowerContent.includes("sqlite")) {
|
|
1989
|
+
if (!detected.databases.includes("sqlite")) detected.databases.push("sqlite");
|
|
1990
|
+
}
|
|
1991
|
+
if (lowerContent.includes("pymongo") || lowerContent.includes("motor")) {
|
|
1992
|
+
if (!detected.databases.includes("mongodb")) detected.databases.push("mongodb");
|
|
1993
|
+
}
|
|
1994
|
+
if (lowerContent.includes("redis") || lowerContent.includes("aioredis")) {
|
|
1995
|
+
if (!detected.databases.includes("redis")) detected.databases.push("redis");
|
|
1996
|
+
}
|
|
1997
|
+
if (lowerContent.includes("pymysql") || lowerContent.includes("aiomysql")) {
|
|
1998
|
+
if (!detected.databases.includes("mysql")) detected.databases.push("mysql");
|
|
1999
|
+
}
|
|
1924
2000
|
} catch {
|
|
1925
2001
|
}
|
|
1926
2002
|
}
|
|
1927
|
-
}
|
|
1928
|
-
|
|
2003
|
+
}
|
|
2004
|
+
if (fileNames.has("requirements.txt")) {
|
|
1929
2005
|
const reqRes = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/HEAD/requirements.txt`);
|
|
1930
2006
|
if (reqRes.ok) {
|
|
1931
2007
|
try {
|
|
1932
2008
|
const content = (await reqRes.text()).toLowerCase();
|
|
1933
|
-
if (
|
|
1934
|
-
if (content.includes("
|
|
1935
|
-
if (content.includes("
|
|
1936
|
-
if (content.includes("
|
|
2009
|
+
if (!detected.stack.includes("python")) detected.stack.push("python");
|
|
2010
|
+
if (content.includes("fastapi") && !detected.stack.includes("fastapi")) detected.stack.push("fastapi");
|
|
2011
|
+
if (content.includes("django") && !detected.stack.includes("django")) detected.stack.push("django");
|
|
2012
|
+
if (content.includes("flask") && !detected.stack.includes("flask")) detected.stack.push("flask");
|
|
2013
|
+
if (content.includes("sqlalchemy") && !detected.stack.includes("sqlalchemy")) detected.stack.push("sqlalchemy");
|
|
2014
|
+
if (content.includes("asyncpg") || content.includes("psycopg")) {
|
|
2015
|
+
if (!detected.databases.includes("postgresql")) detected.databases.push("postgresql");
|
|
2016
|
+
}
|
|
2017
|
+
if (content.includes("aiosqlite") || content.includes("sqlite")) {
|
|
2018
|
+
if (!detected.databases.includes("sqlite")) detected.databases.push("sqlite");
|
|
2019
|
+
}
|
|
2020
|
+
if (content.includes("pymongo") || content.includes("motor")) {
|
|
2021
|
+
if (!detected.databases.includes("mongodb")) detected.databases.push("mongodb");
|
|
2022
|
+
}
|
|
1937
2023
|
} catch {
|
|
1938
2024
|
}
|
|
1939
2025
|
}
|
|
@@ -1950,11 +2036,16 @@ async function detectFromGitHubApi(repoUrl) {
|
|
|
1950
2036
|
if (allDeps["svelte"]) detected.stack.push("svelte");
|
|
1951
2037
|
if (allDeps["express"]) detected.stack.push("express");
|
|
1952
2038
|
if (allDeps["fastify"]) detected.stack.push("fastify");
|
|
2039
|
+
if (allDeps["hono"]) detected.stack.push("hono");
|
|
1953
2040
|
if (allDeps["typescript"]) detected.stack.push("typescript");
|
|
1954
2041
|
if (allDeps["tailwindcss"]) detected.stack.push("tailwind");
|
|
1955
2042
|
if (allDeps["prisma"]) detected.stack.push("prisma");
|
|
1956
|
-
if (allDeps["
|
|
1957
|
-
if (allDeps["
|
|
2043
|
+
if (allDeps["drizzle-orm"]) detected.stack.push("drizzle");
|
|
2044
|
+
if (allDeps["vitest"]) detected.testFramework = "vitest";
|
|
2045
|
+
else if (allDeps["jest"]) detected.testFramework = "jest";
|
|
2046
|
+
else if (allDeps["@playwright/test"]) detected.testFramework = "playwright";
|
|
2047
|
+
else if (allDeps["cypress"]) detected.testFramework = "cypress";
|
|
2048
|
+
else if (allDeps["mocha"]) detected.testFramework = "mocha";
|
|
1958
2049
|
if (detected.stack.length === 0 || detected.stack.length === 1 && detected.stack[0] === "typescript") {
|
|
1959
2050
|
detected.stack.unshift("javascript");
|
|
1960
2051
|
}
|
|
@@ -1965,30 +2056,35 @@ async function detectFromGitHubApi(repoUrl) {
|
|
|
1965
2056
|
if (pkg.scripts.dev) detected.commands.dev = "npm run dev";
|
|
1966
2057
|
else if (pkg.scripts.start) detected.commands.dev = "npm run start";
|
|
1967
2058
|
}
|
|
2059
|
+
if (allDeps["pg"] || allDeps["postgres"] || allDeps["@neondatabase/serverless"]) {
|
|
2060
|
+
if (!detected.databases.includes("postgresql")) detected.databases.push("postgresql");
|
|
2061
|
+
}
|
|
2062
|
+
if (allDeps["better-sqlite3"] || allDeps["sql.js"] || allDeps["sqlite3"]) {
|
|
2063
|
+
if (!detected.databases.includes("sqlite")) detected.databases.push("sqlite");
|
|
2064
|
+
}
|
|
2065
|
+
if (allDeps["mongodb"] || allDeps["mongoose"]) {
|
|
2066
|
+
if (!detected.databases.includes("mongodb")) detected.databases.push("mongodb");
|
|
2067
|
+
}
|
|
2068
|
+
if (allDeps["redis"] || allDeps["ioredis"]) {
|
|
2069
|
+
if (!detected.databases.includes("redis")) detected.databases.push("redis");
|
|
2070
|
+
}
|
|
2071
|
+
if (allDeps["mysql"] || allDeps["mysql2"]) {
|
|
2072
|
+
if (!detected.databases.includes("mysql")) detected.databases.push("mysql");
|
|
2073
|
+
}
|
|
1968
2074
|
} catch {
|
|
1969
2075
|
}
|
|
1970
2076
|
}
|
|
1971
2077
|
}
|
|
1972
|
-
if (fileNames.has("cargo.toml"))
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
const composeRes = await fetch(`https://raw.githubusercontent.com/${owner}/${repo}/HEAD/docker-compose.yml`);
|
|
1977
|
-
if (composeRes.ok) {
|
|
1978
|
-
try {
|
|
1979
|
-
const content = (await composeRes.text()).toLowerCase();
|
|
1980
|
-
if (content.includes("postgres")) detected.stack.push("postgresql");
|
|
1981
|
-
if (content.includes("mysql")) detected.stack.push("mysql");
|
|
1982
|
-
if (content.includes("mongo")) detected.stack.push("mongodb");
|
|
1983
|
-
if (content.includes("redis")) detected.stack.push("redis");
|
|
1984
|
-
} catch {
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
2078
|
+
if (fileNames.has("cargo.toml")) {
|
|
2079
|
+
detected.stack.push("rust");
|
|
2080
|
+
detected.commands.build = "cargo build";
|
|
2081
|
+
detected.commands.test = "cargo test";
|
|
1987
2082
|
}
|
|
1988
|
-
if (
|
|
1989
|
-
detected.
|
|
2083
|
+
if (fileNames.has("go.mod")) {
|
|
2084
|
+
detected.stack.push("go");
|
|
2085
|
+
detected.commands.build = "go build";
|
|
2086
|
+
detected.commands.test = "go test ./...";
|
|
1990
2087
|
}
|
|
1991
|
-
if (fileNames.has(".gitlab-ci.yml")) detected.cicd = "gitlab_ci";
|
|
1992
2088
|
return detected;
|
|
1993
2089
|
} catch {
|
|
1994
2090
|
return null;
|
|
@@ -2006,16 +2102,24 @@ async function detectFromGitLabApi(repoUrl) {
|
|
|
2006
2102
|
if (!repoRes.ok) return null;
|
|
2007
2103
|
const repoInfo = await repoRes.json();
|
|
2008
2104
|
if (repoInfo.visibility === "private") return null;
|
|
2105
|
+
const licenseId = repoInfo.license?.key?.toLowerCase() || null;
|
|
2106
|
+
const isOpenSource = repoInfo.visibility === "public" && (licenseId ? OPEN_SOURCE_LICENSES.includes(licenseId) : false);
|
|
2009
2107
|
const detected = {
|
|
2010
2108
|
name: repoInfo.name,
|
|
2011
2109
|
description: repoInfo.description ?? void 0,
|
|
2012
2110
|
stack: [],
|
|
2111
|
+
databases: [],
|
|
2013
2112
|
commands: {},
|
|
2014
2113
|
packageManager: null,
|
|
2015
2114
|
type: "application",
|
|
2016
2115
|
repoHost: "gitlab",
|
|
2017
2116
|
repoUrl,
|
|
2018
|
-
license:
|
|
2117
|
+
license: licenseId ?? void 0,
|
|
2118
|
+
isPublicRepo: repoInfo.visibility === "public",
|
|
2119
|
+
isOpenSource,
|
|
2120
|
+
projectType: isOpenSource ? "open_source" : void 0,
|
|
2121
|
+
hasDocker: false,
|
|
2122
|
+
existingFiles: []
|
|
2019
2123
|
};
|
|
2020
2124
|
const filesRes = await fetch(`https://${host}/api/v4/projects/${encodedPath}/repository/tree?per_page=100`, {
|
|
2021
2125
|
headers: { "User-Agent": "LynxPrompt-CLI" }
|
|
@@ -2023,6 +2127,39 @@ async function detectFromGitLabApi(repoUrl) {
|
|
|
2023
2127
|
if (!filesRes.ok) return detected;
|
|
2024
2128
|
const files = await filesRes.json();
|
|
2025
2129
|
const fileNames = new Set(files.map((f) => f.name.toLowerCase()));
|
|
2130
|
+
for (const file of STATIC_FILES) {
|
|
2131
|
+
if (files.some((f) => f.name.toLowerCase() === file.toLowerCase())) {
|
|
2132
|
+
detected.existingFiles.push(file);
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
if (fileNames.has(".gitlab-ci.yml")) detected.cicd = "gitlab_ci";
|
|
2136
|
+
if (fileNames.has("jenkinsfile")) detected.cicd = "jenkins";
|
|
2137
|
+
if (fileNames.has("dockerfile") || fileNames.has("docker-compose.yml") || fileNames.has("docker-compose.yaml")) {
|
|
2138
|
+
detected.hasDocker = true;
|
|
2139
|
+
detected.stack.push("docker");
|
|
2140
|
+
const dockerComposeFile = fileNames.has("docker-compose.yml") ? "docker-compose.yml" : fileNames.has("docker-compose.yaml") ? "docker-compose.yaml" : null;
|
|
2141
|
+
if (dockerComposeFile) {
|
|
2142
|
+
const composeRes = await fetch(`https://${host}/api/v4/projects/${encodedPath}/repository/files/${encodeURIComponent(dockerComposeFile)}/raw?ref=HEAD`, {
|
|
2143
|
+
headers: { "User-Agent": "LynxPrompt-CLI" }
|
|
2144
|
+
});
|
|
2145
|
+
if (composeRes.ok) {
|
|
2146
|
+
try {
|
|
2147
|
+
const content = await composeRes.text();
|
|
2148
|
+
const lowerContent = content.toLowerCase();
|
|
2149
|
+
if (content.includes("registry.gitlab.com")) detected.containerRegistry = "gitlab_registry";
|
|
2150
|
+
else if (content.includes("ghcr.io")) detected.containerRegistry = "ghcr";
|
|
2151
|
+
else if (content.includes("docker.io") || /image:\s*[a-z0-9]+\/[a-z0-9]/.test(content)) detected.containerRegistry = "dockerhub";
|
|
2152
|
+
else if (content.includes("gcr.io")) detected.containerRegistry = "gcr";
|
|
2153
|
+
if (lowerContent.includes("postgres")) detected.databases.push("postgresql");
|
|
2154
|
+
if (lowerContent.includes("mysql") && !lowerContent.includes("mysql-")) detected.databases.push("mysql");
|
|
2155
|
+
if (lowerContent.includes("mongo")) detected.databases.push("mongodb");
|
|
2156
|
+
if (lowerContent.includes("redis")) detected.databases.push("redis");
|
|
2157
|
+
if (lowerContent.includes("sqlite")) detected.databases.push("sqlite");
|
|
2158
|
+
} catch {
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2026
2163
|
if (fileNames.has("package.json")) {
|
|
2027
2164
|
const pkgRes = await fetch(`https://${host}/api/v4/projects/${encodedPath}/repository/files/package.json/raw?ref=HEAD`, {
|
|
2028
2165
|
headers: { "User-Agent": "LynxPrompt-CLI" }
|
|
@@ -2033,9 +2170,17 @@ async function detectFromGitLabApi(repoUrl) {
|
|
|
2033
2170
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
2034
2171
|
if (allDeps["next"]) detected.stack.push("nextjs");
|
|
2035
2172
|
if (allDeps["react"]) detected.stack.push("react");
|
|
2173
|
+
if (allDeps["vue"]) detected.stack.push("vue");
|
|
2174
|
+
if (allDeps["svelte"]) detected.stack.push("svelte");
|
|
2175
|
+
if (allDeps["express"]) detected.stack.push("express");
|
|
2176
|
+
if (allDeps["fastify"]) detected.stack.push("fastify");
|
|
2036
2177
|
if (allDeps["typescript"]) detected.stack.push("typescript");
|
|
2037
2178
|
if (allDeps["tailwindcss"]) detected.stack.push("tailwind");
|
|
2038
|
-
if (detected.stack.
|
|
2179
|
+
if (allDeps["prisma"]) detected.stack.push("prisma");
|
|
2180
|
+
if (allDeps["vitest"]) detected.testFramework = "vitest";
|
|
2181
|
+
else if (allDeps["jest"]) detected.testFramework = "jest";
|
|
2182
|
+
else if (allDeps["@playwright/test"]) detected.testFramework = "playwright";
|
|
2183
|
+
if (detected.stack.length === 0 || detected.stack.length === 1 && detected.stack[0] === "typescript") {
|
|
2039
2184
|
detected.stack.unshift("javascript");
|
|
2040
2185
|
}
|
|
2041
2186
|
if (pkg.scripts) {
|
|
@@ -2044,15 +2189,57 @@ async function detectFromGitLabApi(repoUrl) {
|
|
|
2044
2189
|
if (pkg.scripts.lint) detected.commands.lint = "npm run lint";
|
|
2045
2190
|
if (pkg.scripts.dev) detected.commands.dev = "npm run dev";
|
|
2046
2191
|
}
|
|
2192
|
+
if (allDeps["pg"] || allDeps["postgres"]) {
|
|
2193
|
+
if (!detected.databases.includes("postgresql")) detected.databases.push("postgresql");
|
|
2194
|
+
}
|
|
2195
|
+
if (allDeps["better-sqlite3"] || allDeps["sqlite3"]) {
|
|
2196
|
+
if (!detected.databases.includes("sqlite")) detected.databases.push("sqlite");
|
|
2197
|
+
}
|
|
2198
|
+
if (allDeps["mongodb"] || allDeps["mongoose"]) {
|
|
2199
|
+
if (!detected.databases.includes("mongodb")) detected.databases.push("mongodb");
|
|
2200
|
+
}
|
|
2201
|
+
if (allDeps["redis"] || allDeps["ioredis"]) {
|
|
2202
|
+
if (!detected.databases.includes("redis")) detected.databases.push("redis");
|
|
2203
|
+
}
|
|
2047
2204
|
} catch {
|
|
2048
2205
|
}
|
|
2049
2206
|
}
|
|
2050
2207
|
}
|
|
2051
|
-
if (fileNames.has("pyproject.toml")
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2208
|
+
if (fileNames.has("pyproject.toml")) {
|
|
2209
|
+
detected.stack.push("python");
|
|
2210
|
+
const pyRes = await fetch(`https://${host}/api/v4/projects/${encodedPath}/repository/files/pyproject.toml/raw?ref=HEAD`, {
|
|
2211
|
+
headers: { "User-Agent": "LynxPrompt-CLI" }
|
|
2212
|
+
});
|
|
2213
|
+
if (pyRes.ok) {
|
|
2214
|
+
try {
|
|
2215
|
+
const content = (await pyRes.text()).toLowerCase();
|
|
2216
|
+
if (content.includes("fastapi")) detected.stack.push("fastapi");
|
|
2217
|
+
if (content.includes("django")) detected.stack.push("django");
|
|
2218
|
+
if (content.includes("flask")) detected.stack.push("flask");
|
|
2219
|
+
if (content.includes("sqlalchemy")) detected.stack.push("sqlalchemy");
|
|
2220
|
+
if (content.includes("pytest")) detected.testFramework = "pytest";
|
|
2221
|
+
if (content.includes("asyncpg") || content.includes("psycopg")) {
|
|
2222
|
+
if (!detected.databases.includes("postgresql")) detected.databases.push("postgresql");
|
|
2223
|
+
}
|
|
2224
|
+
if (content.includes("aiosqlite") || content.includes("sqlite")) {
|
|
2225
|
+
if (!detected.databases.includes("sqlite")) detected.databases.push("sqlite");
|
|
2226
|
+
}
|
|
2227
|
+
} catch {
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
} else if (fileNames.has("requirements.txt")) {
|
|
2231
|
+
detected.stack.push("python");
|
|
2232
|
+
}
|
|
2233
|
+
if (fileNames.has("cargo.toml")) {
|
|
2234
|
+
detected.stack.push("rust");
|
|
2235
|
+
detected.commands.build = "cargo build";
|
|
2236
|
+
detected.commands.test = "cargo test";
|
|
2237
|
+
}
|
|
2238
|
+
if (fileNames.has("go.mod")) {
|
|
2239
|
+
detected.stack.push("go");
|
|
2240
|
+
detected.commands.build = "go build";
|
|
2241
|
+
detected.commands.test = "go test ./...";
|
|
2242
|
+
}
|
|
2056
2243
|
return detected;
|
|
2057
2244
|
} catch {
|
|
2058
2245
|
return null;
|
|
@@ -3400,7 +3587,7 @@ function generateYamlConfig(options, platform2) {
|
|
|
3400
3587
|
|
|
3401
3588
|
// src/commands/wizard.ts
|
|
3402
3589
|
var DRAFTS_DIR = ".lynxprompt/drafts";
|
|
3403
|
-
var CLI_VERSION = "1.2.
|
|
3590
|
+
var CLI_VERSION = "1.2.12";
|
|
3404
3591
|
async function saveDraftLocally(name, config2, stepReached) {
|
|
3405
3592
|
const draftsPath = join4(process.cwd(), DRAFTS_DIR);
|
|
3406
3593
|
await mkdir3(draftsPath, { recursive: true });
|
|
@@ -4496,13 +4683,24 @@ async function runWizardWithDraftProtection(options) {
|
|
|
4496
4683
|
console.log();
|
|
4497
4684
|
console.log(chalk7.white(` Name: ${detected2.name || "unknown"}`));
|
|
4498
4685
|
if (detected2.description) console.log(chalk7.gray(` Description: ${detected2.description}`));
|
|
4686
|
+
console.log(chalk7.white(` Type: ${detected2.isOpenSource ? "Open Source" : detected2.type}`));
|
|
4499
4687
|
console.log(chalk7.white(` Stack: ${detected2.stack.join(", ") || "none detected"}`));
|
|
4500
|
-
|
|
4688
|
+
if (detected2.databases && detected2.databases.length > 0) {
|
|
4689
|
+
console.log(chalk7.white(` Databases: ${detected2.databases.join(", ")}`));
|
|
4690
|
+
}
|
|
4501
4691
|
if (detected2.packageManager) console.log(chalk7.white(` Package Manager: ${detected2.packageManager}`));
|
|
4502
|
-
if (detected2.repoHost) console.log(chalk7.white(`
|
|
4503
|
-
if (detected2.license) console.log(chalk7.white(` License: ${detected2.license}`));
|
|
4504
|
-
if (detected2.cicd) console.log(chalk7.white(` CI/CD: ${detected2.cicd}`));
|
|
4505
|
-
if (detected2.hasDocker)
|
|
4692
|
+
if (detected2.repoHost) console.log(chalk7.white(` Host: ${detected2.repoHost}`));
|
|
4693
|
+
if (detected2.license) console.log(chalk7.white(` License: ${detected2.license.toUpperCase()}`));
|
|
4694
|
+
if (detected2.cicd) console.log(chalk7.white(` CI/CD: ${detected2.cicd.replace("_", " ")}`));
|
|
4695
|
+
if (detected2.hasDocker) {
|
|
4696
|
+
const dockerInfo = detected2.containerRegistry ? `detected (registry: ${detected2.containerRegistry})` : "detected";
|
|
4697
|
+
console.log(chalk7.white(` Docker: ${dockerInfo}`));
|
|
4698
|
+
}
|
|
4699
|
+
if (detected2.testFramework) console.log(chalk7.white(` Test Framework: ${detected2.testFramework}`));
|
|
4700
|
+
if (detected2.existingFiles && detected2.existingFiles.length > 0) {
|
|
4701
|
+
const filesDisplay = detected2.existingFiles.length > 3 ? `${detected2.existingFiles.slice(0, 3).join(", ")}... (+${detected2.existingFiles.length - 3})` : detected2.existingFiles.join(", ");
|
|
4702
|
+
console.log(chalk7.white(` Static files found: ${detected2.existingFiles.length} (${filesDisplay})`));
|
|
4703
|
+
}
|
|
4506
4704
|
if (detected2.commands) {
|
|
4507
4705
|
console.log(chalk7.white(` Commands:`));
|
|
4508
4706
|
if (detected2.commands.build) console.log(chalk7.gray(` build: ${detected2.commands.build}`));
|
|
@@ -4633,7 +4831,22 @@ async function runWizardWithDraftProtection(options) {
|
|
|
4633
4831
|
chalk7.green("\u2713 Remote project detected")
|
|
4634
4832
|
];
|
|
4635
4833
|
if (detected.name) detectedInfo.push(chalk7.gray(` Name: ${detected.name}`));
|
|
4834
|
+
if (detected.isOpenSource) detectedInfo.push(chalk7.gray(` Type: Open Source`));
|
|
4636
4835
|
if (detected.stack.length > 0) detectedInfo.push(chalk7.gray(` Stack: ${detected.stack.join(", ")}`));
|
|
4836
|
+
if (detected.databases && detected.databases.length > 0) {
|
|
4837
|
+
detectedInfo.push(chalk7.gray(` Databases: ${detected.databases.join(", ")}`));
|
|
4838
|
+
}
|
|
4839
|
+
if (detected.license) detectedInfo.push(chalk7.gray(` License: ${detected.license.toUpperCase()}`));
|
|
4840
|
+
if (detected.repoHost) detectedInfo.push(chalk7.gray(` Host: ${detected.repoHost}`));
|
|
4841
|
+
if (detected.cicd) detectedInfo.push(chalk7.gray(` CI/CD: ${detected.cicd.replace("_", " ")}`));
|
|
4842
|
+
if (detected.hasDocker) {
|
|
4843
|
+
const dockerInfo = detected.containerRegistry ? `detected (registry: ${detected.containerRegistry})` : "detected";
|
|
4844
|
+
detectedInfo.push(chalk7.gray(` Docker: ${dockerInfo}`));
|
|
4845
|
+
}
|
|
4846
|
+
if (detected.existingFiles && detected.existingFiles.length > 0) {
|
|
4847
|
+
const filesDisplay = detected.existingFiles.length > 3 ? `${detected.existingFiles.slice(0, 3).join(", ")}...` : detected.existingFiles.join(", ");
|
|
4848
|
+
detectedInfo.push(chalk7.gray(` Static files found: ${detected.existingFiles.length} (${filesDisplay})`));
|
|
4849
|
+
}
|
|
4637
4850
|
if (detected.repoUrl) detectedInfo.push(chalk7.gray(` Source: ${detected.repoUrl}`));
|
|
4638
4851
|
printBox(detectedInfo, chalk7.gray);
|
|
4639
4852
|
console.log();
|
|
@@ -8597,7 +8810,7 @@ function handleError2(error) {
|
|
|
8597
8810
|
}
|
|
8598
8811
|
|
|
8599
8812
|
// src/index.ts
|
|
8600
|
-
var CLI_VERSION2 = "1.2.
|
|
8813
|
+
var CLI_VERSION2 = "1.2.12";
|
|
8601
8814
|
var program = new Command();
|
|
8602
8815
|
program.name("lynxprompt").description("CLI for LynxPrompt - Generate AI IDE configuration files").version(CLI_VERSION2);
|
|
8603
8816
|
program.command("wizard").description("Generate AI IDE configuration (recommended for most users)").option("-n, --name <name>", "Project name").option("-d, --description <description>", "Project description").option("-s, --stack <stack>", "Tech stack (comma-separated)").option("-f, --format <format>", "Output format: agents, cursor, or comma-separated for multiple").option("-p, --platforms <platforms>", "Alias for --format (deprecated)").option("--persona <persona>", "AI persona (fullstack, backend, frontend, devops, data, security)").option("--boundaries <level>", "Boundary preset (conservative, standard, permissive)").option("-y, --yes", "Skip prompts, use defaults (generates AGENTS.md)").option("-o, --output <dir>", "Output directory (default: current directory)").option("--repo-url <url>", "Analyze remote repository URL (GitHub/GitLab supported)").option("--blueprint", "Generate with [[VARIABLE|default]] placeholders for templates").option("--license <type>", "License type (mit, apache-2.0, gpl-3.0, etc.)").option("--ci-cd <platform>", "CI/CD platform (github_actions, gitlab_ci, jenkins, etc.)").option("--project-type <type>", "Project type (work, leisure, opensource, learning)").option("--detect-only", "Only detect project info, don't generate files").option("--load-draft <name>", "Load a saved wizard draft").option("--save-draft <name>", "Save wizard state as a draft (auto-saves at end)").option("--vars <values>", "Fill variables: VAR1=value1,VAR2=value2").action(wizardCommand);
|