xoxohp 1.0.4 → 1.0.6
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/index.js +71 -191
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -1,233 +1,113 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// const fs = require('fs'); // Node.js File System
|
|
4
|
-
// const path = require('path'); // Node.js Path module
|
|
5
|
-
// const yargs = require('yargs/yargs');
|
|
6
|
-
// const { hideBin } = require('yargs/helpers');
|
|
7
|
-
|
|
8
|
-
// // ⚠️ Paste your official Google Gemini API key here.
|
|
9
|
-
// const API_KEY = "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";
|
|
10
|
-
|
|
11
|
-
// /**
|
|
12
|
-
// * Generates a full project structure based on a prompt.
|
|
13
|
-
// * @param {string} prompt - The user's project request.
|
|
14
|
-
// * @param {string} directoryName - The name of the folder to create the project in.
|
|
15
|
-
// */
|
|
16
|
-
// async function generateProject(prompt, directoryName) {
|
|
17
|
-
// const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${API_KEY}`;
|
|
18
|
-
|
|
19
|
-
// // --- This is the new, "smarter" prompt ---
|
|
20
|
-
// // We are asking the AI to act as a file structure generator
|
|
21
|
-
// // and return a specific JSON format.
|
|
22
|
-
// const newPrompt = `
|
|
23
|
-
// You are an expert software developer and project scaffolder.
|
|
24
|
-
// Based on the user's prompt, generate a complete file structure as a JSON array.
|
|
25
|
-
// Each object in the array must have two keys:
|
|
26
|
-
// 1. "filename": (string) The full relative path for the file (e.g., "index.html", "src/styles.css", "js/app.js").
|
|
27
|
-
// 2. "code": (string) The complete code for that file.
|
|
28
|
-
|
|
29
|
-
// Only return the raw JSON array, with no other text, explanations, or markdown fences.
|
|
30
|
-
|
|
31
|
-
// User Prompt: "${prompt}"
|
|
32
|
-
// `;
|
|
33
|
-
|
|
34
|
-
// const body = {
|
|
35
|
-
// contents: [{ parts: [{ text: newPrompt }] }]
|
|
36
|
-
// };
|
|
37
|
-
|
|
38
|
-
// try {
|
|
39
|
-
// console.log(`Code Running in Expresss`);
|
|
40
|
-
|
|
41
|
-
// const response = await fetch(url, {
|
|
42
|
-
// method: 'POST',
|
|
43
|
-
// headers: { 'Content-Type': 'application/json' },
|
|
44
|
-
// body: JSON.stringify(body),
|
|
45
|
-
// });
|
|
46
|
-
|
|
47
|
-
// if (!response.ok) {
|
|
48
|
-
// const errorData = await response.json();
|
|
49
|
-
// console.error('❌ API Error Details:', JSON.stringify(errorData.error, null, 2));
|
|
50
|
-
// throw new Error(`API request failed with status ${response.status}`);
|
|
51
|
-
// }
|
|
52
|
-
|
|
53
|
-
// const data = await response.json();
|
|
54
|
-
// let responseText = data.candidates[0].content.parts[0].text;
|
|
55
|
-
|
|
56
|
-
// // --- NEW JSON PARSING & FILE CREATION LOGIC ---
|
|
57
|
-
// // console.log("Building project...");
|
|
58
|
-
|
|
59
|
-
// // Clean up potential markdown fences from the AI's response
|
|
60
|
-
// if (responseText.startsWith("```json")) {
|
|
61
|
-
// responseText = responseText.substring(7, responseText.length - 3).trim();
|
|
62
|
-
// }
|
|
63
|
-
|
|
64
|
-
// let files;
|
|
65
|
-
// try {
|
|
66
|
-
// files = JSON.parse(responseText);
|
|
67
|
-
// if (!Array.isArray(files)) throw new Error("AI did not return a JSON array.");
|
|
68
|
-
// } catch (parseError) {
|
|
69
|
-
// console.error("❌ ERROR: Failed to parse the AI's response. The response was not valid JSON.");
|
|
70
|
-
// console.error("Raw AI Response:", responseText);
|
|
71
|
-
// return;
|
|
72
|
-
// }
|
|
73
|
-
|
|
74
|
-
// // Create the main project directory
|
|
75
|
-
// fs.mkdirSync(directoryName, { recursive: true });
|
|
76
|
-
// console.log(``);
|
|
77
|
-
|
|
78
|
-
// // Loop through the files array and create each file
|
|
79
|
-
// for (const file of files) {
|
|
80
|
-
// const filePath = path.join(directoryName, file.filename);
|
|
81
|
-
// const fileDir = path.dirname(filePath);
|
|
82
|
-
|
|
83
|
-
// // Create subdirectories if they don't exist
|
|
84
|
-
// if (!fs.existsSync(fileDir)) {
|
|
85
|
-
// fs.mkdirSync(fileDir, { recursive: true });
|
|
86
|
-
// }
|
|
87
|
-
|
|
88
|
-
// // Write the code to the file
|
|
89
|
-
// fs.writeFileSync(filePath, file.code);
|
|
90
|
-
// //console.log(`Created file: ${filePath}`);
|
|
91
|
-
// }
|
|
92
|
-
|
|
93
|
-
// // console.log(`\n🎉 Project "${directoryName}" created successfully!`);
|
|
94
|
-
|
|
95
|
-
// } catch (error) {
|
|
96
|
-
// console.error('❌ An error occurred:', error.message);
|
|
97
|
-
// }
|
|
98
|
-
// }
|
|
99
|
-
|
|
100
|
-
// // --- NEW YARGS SETUP ---
|
|
101
|
-
// yargs(hideBin(process.argv))
|
|
102
|
-
// .command(
|
|
103
|
-
// '$0 <prompt>', // The default command
|
|
104
|
-
// 'Generates a full project structure from a text prompt.',
|
|
105
|
-
// (yargs) => {
|
|
106
|
-
// return yargs
|
|
107
|
-
// .positional('prompt', {
|
|
108
|
-
// describe: 'The project you want to generate',
|
|
109
|
-
// type: 'string',
|
|
110
|
-
// })
|
|
111
|
-
// .option('directory', { // Replaces the old 'output' flag
|
|
112
|
-
// alias: 'd',
|
|
113
|
-
// describe: 'The name of the new directory to create the project in',
|
|
114
|
-
// type: 'string',
|
|
115
|
-
// demandOption: true, // This flag is now required
|
|
116
|
-
// });
|
|
117
|
-
// },
|
|
118
|
-
// (argv) => {
|
|
119
|
-
// if (!API_KEY || API_KEY === "YOUR_GEMINI_API_KEY_HERE") {
|
|
120
|
-
// console.error('❌ ERROR: Please add your API key to the index.js file.');
|
|
121
|
-
// return;
|
|
122
|
-
// }
|
|
123
|
-
// generateProject(argv.prompt, argv.directory);
|
|
124
|
-
// }
|
|
125
|
-
// )
|
|
126
|
-
// .demandCommand(1, 'Please provide a prompt.')
|
|
127
|
-
// .parse();
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
// #!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
131
2
|
|
|
132
3
|
const fs = require('fs');
|
|
133
4
|
const path = require('path');
|
|
134
5
|
const yargs = require('yargs/yargs');
|
|
135
6
|
const { hideBin } = require('yargs/helpers');
|
|
7
|
+
const OpenAI = require('openai');
|
|
136
8
|
|
|
137
|
-
//
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
// 🔐 Put your OpenAI API key here or use process.env.OPENAI_API_KEY
|
|
142
|
-
const API_KEY = process.env.OPENAI_API_KEY || "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";
|
|
9
|
+
// 🔴 PASTE YOUR OPENAI API KEY HERE (starts with sk-)
|
|
10
|
+
const client = new OpenAI({
|
|
11
|
+
apiKey: "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"
|
|
12
|
+
});
|
|
143
13
|
|
|
144
14
|
/**
|
|
145
|
-
* Generates a full project structure based on a prompt
|
|
15
|
+
* Generates a full project structure based on a prompt
|
|
16
|
+
* @param {string} prompt
|
|
17
|
+
* @param {string} directoryName
|
|
146
18
|
*/
|
|
147
19
|
async function generateProject(prompt, directoryName) {
|
|
148
|
-
const url = "https://api.openai.com/v1/responses";
|
|
149
20
|
|
|
150
|
-
const
|
|
21
|
+
const systemPrompt = `
|
|
151
22
|
You are an expert software developer and project scaffolder.
|
|
152
|
-
Return a JSON array of files.
|
|
153
|
-
Each item must contain:
|
|
154
|
-
- filename
|
|
155
|
-
- code
|
|
156
23
|
|
|
157
|
-
|
|
24
|
+
Generate a COMPLETE project structure as a JSON array.
|
|
25
|
+
Each object MUST have:
|
|
26
|
+
1. "filename" → string (relative path, e.g. "src/index.js")
|
|
27
|
+
2. "code" → string (full file content)
|
|
158
28
|
|
|
159
|
-
|
|
29
|
+
IMPORTANT RULES:
|
|
30
|
+
- Return ONLY raw JSON
|
|
31
|
+
- NO markdown
|
|
32
|
+
- NO explanation
|
|
33
|
+
- NO backticks
|
|
160
34
|
`;
|
|
161
35
|
|
|
162
|
-
const body = {
|
|
163
|
-
model: "gpt-4.1-mini",
|
|
164
|
-
input: newPrompt,
|
|
165
|
-
max_output_tokens: 3000
|
|
166
|
-
};
|
|
167
|
-
|
|
168
36
|
try {
|
|
169
|
-
console.log("Generating project...");
|
|
170
|
-
|
|
171
|
-
const response = await
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
"
|
|
176
|
-
|
|
177
|
-
|
|
37
|
+
console.log("🚀 Generating project with OpenAI...");
|
|
38
|
+
|
|
39
|
+
const response = await client.chat.completions.create({
|
|
40
|
+
model: "gpt-4o-mini",
|
|
41
|
+
temperature: 0.2,
|
|
42
|
+
messages: [
|
|
43
|
+
{ role: "system", content: systemPrompt },
|
|
44
|
+
{ role: "user", content: prompt }
|
|
45
|
+
]
|
|
178
46
|
});
|
|
179
47
|
|
|
180
|
-
|
|
181
|
-
throw new Error(await response.text());
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const data = await response.json();
|
|
185
|
-
|
|
186
|
-
let responseText =
|
|
187
|
-
data.output_text ||
|
|
188
|
-
data.output?.[0]?.content?.[0]?.text ||
|
|
189
|
-
"";
|
|
48
|
+
let text = response.choices[0].message.content.trim();
|
|
190
49
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
.replace(
|
|
194
|
-
|
|
50
|
+
// Cleanup (extra safety)
|
|
51
|
+
if (text.startsWith("```")) {
|
|
52
|
+
text = text.replace(/```json|```/g, "").trim();
|
|
53
|
+
}
|
|
195
54
|
|
|
196
|
-
let files
|
|
55
|
+
let files;
|
|
56
|
+
try {
|
|
57
|
+
files = JSON.parse(text);
|
|
58
|
+
if (!Array.isArray(files)) throw new Error();
|
|
59
|
+
} catch {
|
|
60
|
+
console.error("❌ ERROR: Invalid JSON returned by OpenAI");
|
|
61
|
+
console.error(text);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
197
64
|
|
|
65
|
+
// Create main directory
|
|
198
66
|
fs.mkdirSync(directoryName, { recursive: true });
|
|
199
67
|
|
|
68
|
+
// Create files
|
|
200
69
|
for (const file of files) {
|
|
201
70
|
const filePath = path.join(directoryName, file.filename);
|
|
202
|
-
|
|
71
|
+
const fileDir = path.dirname(filePath);
|
|
72
|
+
|
|
73
|
+
if (!fs.existsSync(fileDir)) {
|
|
74
|
+
fs.mkdirSync(fileDir, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
|
|
203
77
|
fs.writeFileSync(filePath, file.code);
|
|
204
78
|
}
|
|
205
79
|
|
|
206
|
-
console.log(
|
|
80
|
+
console.log(`✅ Project "${directoryName}" created successfully!`);
|
|
207
81
|
|
|
208
|
-
} catch (
|
|
209
|
-
console.error("❌ Error:",
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error("❌ OpenAI API Error:", error.message);
|
|
210
84
|
}
|
|
211
85
|
}
|
|
212
86
|
|
|
213
|
-
// CLI
|
|
87
|
+
// CLI setup
|
|
214
88
|
yargs(hideBin(process.argv))
|
|
215
89
|
.command(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
90
|
+
'$0 <prompt>',
|
|
91
|
+
'Generate a full project structure from a text prompt',
|
|
92
|
+
(yargs) =>
|
|
93
|
+
yargs
|
|
94
|
+
.positional('prompt', {
|
|
95
|
+
describe: 'Describe the project',
|
|
96
|
+
type: 'string',
|
|
97
|
+
})
|
|
98
|
+
.option('directory', {
|
|
99
|
+
alias: 'd',
|
|
100
|
+
describe: 'Output directory name',
|
|
101
|
+
type: 'string',
|
|
102
|
+
demandOption: true,
|
|
103
|
+
}),
|
|
224
104
|
(argv) => {
|
|
225
|
-
if (!
|
|
226
|
-
console.error("❌
|
|
105
|
+
if (!client.apiKey || client.apiKey.startsWith("sk-") === false) {
|
|
106
|
+
console.error("❌ ERROR: Invalid OpenAI API key");
|
|
227
107
|
return;
|
|
228
108
|
}
|
|
229
109
|
generateProject(argv.prompt, argv.directory);
|
|
230
110
|
}
|
|
231
111
|
)
|
|
112
|
+
.demandCommand(1, 'Please provide a prompt')
|
|
232
113
|
.parse();
|
|
233
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xoxohp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"bin":{
|
|
6
6
|
"xoxohp":"./index.js"
|
|
@@ -14,6 +14,6 @@
|
|
|
14
14
|
"type": "commonjs",
|
|
15
15
|
"description": "",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"yargs": "^
|
|
17
|
+
"yargs": "^17.7.2"
|
|
18
18
|
}
|
|
19
19
|
}
|