@forvibe/cli 0.1.0 → 1.0.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/dist/index.js +41 -128
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1885,61 +1885,6 @@ var ForvibeClient = class {
|
|
|
1885
1885
|
}
|
|
1886
1886
|
return await response.json();
|
|
1887
1887
|
}
|
|
1888
|
-
/**
|
|
1889
|
-
* Send raw project data to backend for AI analysis (Gemini proxy)
|
|
1890
|
-
*/
|
|
1891
|
-
async analyzeProject(input) {
|
|
1892
|
-
if (!this.sessionToken) {
|
|
1893
|
-
throw new Error("Not connected. Please validate OTC code first.");
|
|
1894
|
-
}
|
|
1895
|
-
const response = await fetch(`${this.baseUrl}/api/agent/analyze`, {
|
|
1896
|
-
method: "POST",
|
|
1897
|
-
headers: {
|
|
1898
|
-
"Content-Type": "application/json",
|
|
1899
|
-
Authorization: `Bearer ${this.sessionToken}`
|
|
1900
|
-
},
|
|
1901
|
-
body: JSON.stringify({
|
|
1902
|
-
tech_stack: {
|
|
1903
|
-
stack: input.techStack.stack,
|
|
1904
|
-
label: input.techStack.label,
|
|
1905
|
-
platforms: input.techStack.platforms,
|
|
1906
|
-
configFiles: input.techStack.configFiles
|
|
1907
|
-
},
|
|
1908
|
-
config: {
|
|
1909
|
-
app_name: input.config.app_name,
|
|
1910
|
-
bundle_id: input.config.bundle_id,
|
|
1911
|
-
version: input.config.version,
|
|
1912
|
-
min_ios_version: input.config.min_ios_version,
|
|
1913
|
-
min_android_sdk: input.config.min_android_sdk,
|
|
1914
|
-
description: input.config.description
|
|
1915
|
-
},
|
|
1916
|
-
sdk_scan: {
|
|
1917
|
-
detected_sdks: input.sdkScan.detected_sdks,
|
|
1918
|
-
data_collected: input.sdkScan.data_collected,
|
|
1919
|
-
advertising_type: input.sdkScan.advertising_type,
|
|
1920
|
-
third_party_services: input.sdkScan.third_party_services,
|
|
1921
|
-
has_iap: input.sdkScan.has_iap
|
|
1922
|
-
},
|
|
1923
|
-
branding: {
|
|
1924
|
-
primary_color: input.branding.primary_color,
|
|
1925
|
-
secondary_color: input.branding.secondary_color,
|
|
1926
|
-
app_icon_base64: input.branding.app_icon_base64
|
|
1927
|
-
},
|
|
1928
|
-
readme_content: input.readmeContent,
|
|
1929
|
-
source_code: input.sourceCode,
|
|
1930
|
-
project_tree: input.projectTree
|
|
1931
|
-
}),
|
|
1932
|
-
signal: AbortSignal.timeout(12e4)
|
|
1933
|
-
});
|
|
1934
|
-
if (!response.ok) {
|
|
1935
|
-
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
1936
|
-
if (response.status === 401) {
|
|
1937
|
-
throw new Error("Session expired. Please generate a new connection code.");
|
|
1938
|
-
}
|
|
1939
|
-
throw new Error(error.error || `Analysis failed (${response.status})`);
|
|
1940
|
-
}
|
|
1941
|
-
return await response.json();
|
|
1942
|
-
}
|
|
1943
1888
|
};
|
|
1944
1889
|
|
|
1945
1890
|
// src/commands/analyze.ts
|
|
@@ -1962,6 +1907,15 @@ async function analyzeCommand(options) {
|
|
|
1962
1907
|
chalk.bold(" Forvibe CLI") + chalk.gray(" \u2014 AI-powered App Store automation")
|
|
1963
1908
|
);
|
|
1964
1909
|
console.log();
|
|
1910
|
+
const geminiApiKey = process.env.GEMINI_API_KEY || process.env.GOOGLE_AI_API_KEY;
|
|
1911
|
+
if (!geminiApiKey) {
|
|
1912
|
+
console.log(chalk.red(" \u2717 Gemini API key is required for project analysis.\n"));
|
|
1913
|
+
console.log(chalk.white(" Set your API key:"));
|
|
1914
|
+
console.log(chalk.cyan(" export GEMINI_API_KEY=your-api-key-here\n"));
|
|
1915
|
+
console.log(chalk.gray(" Get a free API key at: https://aistudio.google.com/apikey"));
|
|
1916
|
+
console.log(chalk.gray(" Your source code is analyzed locally \u2014 it never leaves your machine.\n"));
|
|
1917
|
+
process.exit(1);
|
|
1918
|
+
}
|
|
1965
1919
|
const otcCode = await askQuestion(
|
|
1966
1920
|
chalk.cyan(" \u{1F517} Enter your Forvibe connection code: ")
|
|
1967
1921
|
);
|
|
@@ -2061,78 +2015,40 @@ async function analyzeCommand(options) {
|
|
|
2061
2015
|
`Source code: ${chalk.bold(String(sourceLines))} lines analyzed ${readmeContent ? chalk.gray("(README found)") : ""}`
|
|
2062
2016
|
);
|
|
2063
2017
|
console.log();
|
|
2064
|
-
const useLocalAI = options.local && (process.env.GEMINI_API_KEY || process.env.GOOGLE_AI_API_KEY);
|
|
2065
2018
|
let report;
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
);
|
|
2079
|
-
if (appAssets.length > 0) {
|
|
2080
|
-
report.app_assets = appAssets;
|
|
2081
|
-
}
|
|
2082
|
-
aiSpinner.succeed(chalk.green("Analysis complete!"));
|
|
2083
|
-
} catch (error) {
|
|
2084
|
-
aiSpinner.fail(
|
|
2085
|
-
chalk.red(`AI analysis failed: ${error instanceof Error ? error.message : "Unknown error"}`)
|
|
2086
|
-
);
|
|
2087
|
-
process.exit(1);
|
|
2088
|
-
}
|
|
2089
|
-
const asoSpinner = ora({
|
|
2090
|
-
text: "Generating ASO-optimized store listing...",
|
|
2091
|
-
prefixText: " "
|
|
2092
|
-
}).start();
|
|
2093
|
-
try {
|
|
2094
|
-
const { generateASOContent } = await import("./aso-generator-AZXT6ZCL.js");
|
|
2095
|
-
const asoContent = await generateASOContent(report, geminiApiKey);
|
|
2096
|
-
report.aso_content = asoContent;
|
|
2097
|
-
asoSpinner.succeed(chalk.green("Store listing content generated!"));
|
|
2098
|
-
} catch (error) {
|
|
2099
|
-
asoSpinner.warn(
|
|
2100
|
-
chalk.yellow(`ASO generation skipped: ${error instanceof Error ? error.message : "Unknown error"}`)
|
|
2101
|
-
);
|
|
2102
|
-
}
|
|
2103
|
-
} else {
|
|
2104
|
-
const aiSpinner = ora({
|
|
2105
|
-
text: "Analyzing your project...",
|
|
2106
|
-
prefixText: " "
|
|
2107
|
-
}).start();
|
|
2108
|
-
try {
|
|
2109
|
-
const result = await client.analyzeProject({
|
|
2110
|
-
techStack,
|
|
2111
|
-
config,
|
|
2112
|
-
sdkScan,
|
|
2113
|
-
branding,
|
|
2114
|
-
readmeContent,
|
|
2115
|
-
sourceCode,
|
|
2116
|
-
projectTree
|
|
2117
|
-
});
|
|
2118
|
-
report = result.report;
|
|
2119
|
-
if (appAssets.length > 0) {
|
|
2120
|
-
report.app_assets = appAssets;
|
|
2121
|
-
}
|
|
2122
|
-
if (result.warnings && result.warnings.length > 0) {
|
|
2123
|
-
aiSpinner.succeed(chalk.green("Analysis complete!"));
|
|
2124
|
-
for (const warning of result.warnings) {
|
|
2125
|
-
console.log(chalk.yellow(` \u26A0 ${warning}`));
|
|
2126
|
-
}
|
|
2127
|
-
} else {
|
|
2128
|
-
aiSpinner.succeed(chalk.green("Analysis complete!"));
|
|
2129
|
-
}
|
|
2130
|
-
} catch (error) {
|
|
2131
|
-
aiSpinner.fail(
|
|
2132
|
-
chalk.red(`Analysis failed: ${error instanceof Error ? error.message : "Unknown error"}`)
|
|
2133
|
-
);
|
|
2134
|
-
process.exit(1);
|
|
2019
|
+
const aiSpinner = ora({
|
|
2020
|
+
text: "Analyzing locally with Gemini AI (your source code never leaves your machine)...",
|
|
2021
|
+
prefixText: " "
|
|
2022
|
+
}).start();
|
|
2023
|
+
try {
|
|
2024
|
+
const { generateReport } = await import("./report-generator-NMGCGKPS.js");
|
|
2025
|
+
report = await generateReport(
|
|
2026
|
+
{ techStack, config, sdkScan, branding, readmeContent, sourceCode, projectTree },
|
|
2027
|
+
geminiApiKey
|
|
2028
|
+
);
|
|
2029
|
+
if (appAssets.length > 0) {
|
|
2030
|
+
report.app_assets = appAssets;
|
|
2135
2031
|
}
|
|
2032
|
+
aiSpinner.succeed(chalk.green("Analysis complete!"));
|
|
2033
|
+
} catch (error) {
|
|
2034
|
+
aiSpinner.fail(
|
|
2035
|
+
chalk.red(`AI analysis failed: ${error instanceof Error ? error.message : "Unknown error"}`)
|
|
2036
|
+
);
|
|
2037
|
+
process.exit(1);
|
|
2038
|
+
}
|
|
2039
|
+
const asoSpinner = ora({
|
|
2040
|
+
text: "Generating ASO-optimized store listing...",
|
|
2041
|
+
prefixText: " "
|
|
2042
|
+
}).start();
|
|
2043
|
+
try {
|
|
2044
|
+
const { generateASOContent } = await import("./aso-generator-AZXT6ZCL.js");
|
|
2045
|
+
const asoContent = await generateASOContent(report, geminiApiKey);
|
|
2046
|
+
report.aso_content = asoContent;
|
|
2047
|
+
asoSpinner.succeed(chalk.green("Store listing content generated!"));
|
|
2048
|
+
} catch (error) {
|
|
2049
|
+
asoSpinner.warn(
|
|
2050
|
+
chalk.yellow(`ASO generation skipped: ${error instanceof Error ? error.message : "Unknown error"}`)
|
|
2051
|
+
);
|
|
2136
2052
|
}
|
|
2137
2053
|
console.log();
|
|
2138
2054
|
console.log(chalk.bold(" \u{1F4CB} Report Summary"));
|
|
@@ -2208,8 +2124,5 @@ program.command("analyze", { isDefault: true }).description(
|
|
|
2208
2124
|
"--api-url <url>",
|
|
2209
2125
|
"Forvibe API URL (for development)",
|
|
2210
2126
|
void 0
|
|
2211
|
-
).option(
|
|
2212
|
-
"--local",
|
|
2213
|
-
"Use local Gemini API key instead of Forvibe backend (requires GEMINI_API_KEY env var)"
|
|
2214
2127
|
).action(analyzeCommand);
|
|
2215
2128
|
program.parse();
|