rafaygen-cli 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/bin/rgcli.js +57 -0
- package/deb-build/DEBIAN/control +7 -0
- package/deb-build/usr/bin/rgcli +0 -0
- package/debug_action.js +25 -0
- package/dist/bundle.cjs +111 -0
- package/fetch_annotations.js +18 -0
- package/fetch_logs.js +24 -0
- package/install.sh +30 -0
- package/package.json +41 -0
- package/pkg-config.json +11 -0
- package/rgcli.deb +0 -0
- package/src/agent.js +104 -0
- package/src/auth.js +40 -0
- package/src/ui.js +70 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const token = "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";
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
const jobsRes = await fetch("https://api.github.com/repos/rafay0342/rgcli/actions/runs/26226725358/jobs", {
|
|
5
|
+
headers: { "Authorization": `Bearer ${token}` }
|
|
6
|
+
});
|
|
7
|
+
const jobsData = await jobsRes.json();
|
|
8
|
+
const job = jobsData.jobs[0];
|
|
9
|
+
|
|
10
|
+
console.log("Fetching annotations for job id:", job.id);
|
|
11
|
+
const annRes = await fetch(`https://api.github.com/repos/rafay0342/rgcli/check-runs/${job.id}/annotations`, {
|
|
12
|
+
headers: { "Authorization": `Bearer ${token}` }
|
|
13
|
+
});
|
|
14
|
+
const annData = await annRes.json();
|
|
15
|
+
console.log("Annotations:");
|
|
16
|
+
console.log(JSON.stringify(annData, null, 2));
|
|
17
|
+
}
|
|
18
|
+
main();
|
package/fetch_logs.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const token = "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";
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
const res = await fetch("https://api.github.com/repos/rafay0342/rgcli/actions/runs/26226725358/jobs", {
|
|
5
|
+
headers: { "Authorization": `token ${token}` }
|
|
6
|
+
});
|
|
7
|
+
const data = await res.json();
|
|
8
|
+
const job = data.jobs[0];
|
|
9
|
+
console.log("Steps:");
|
|
10
|
+
for (const step of job.steps) {
|
|
11
|
+
if (step.conclusion === "failure") {
|
|
12
|
+
console.log(`Failed Step: ${step.name}`);
|
|
13
|
+
console.log(step);
|
|
14
|
+
|
|
15
|
+
// Try to get logs for this job
|
|
16
|
+
const logRes = await fetch(job.url + "/logs", { headers: { "Authorization": `token ${token}` }});
|
|
17
|
+
const logs = await logRes.text();
|
|
18
|
+
// Only print the last 50 lines
|
|
19
|
+
console.log("=== LOGS ===");
|
|
20
|
+
console.log(logs.split('\\n').slice(-50).join('\\n'));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
main();
|
package/install.sh
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# RafayGen CLI (rgcli) Installation Script
|
|
3
|
+
|
|
4
|
+
echo "Installing RafayGen CLI..."
|
|
5
|
+
|
|
6
|
+
# Check for Node.js
|
|
7
|
+
if ! command -v npm &> /dev/null; then
|
|
8
|
+
echo "Error: npm is not installed. Please install Node.js first."
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
echo "Installing rgcli globally via npm..."
|
|
13
|
+
npm install -g rgcli
|
|
14
|
+
|
|
15
|
+
echo ""
|
|
16
|
+
echo "=================================================="
|
|
17
|
+
echo "✔ RafayGen CLI installed successfully!"
|
|
18
|
+
echo "=================================================="
|
|
19
|
+
echo ""
|
|
20
|
+
echo "To get started, authenticate with your web app:"
|
|
21
|
+
echo " rgcli login <your-token>"
|
|
22
|
+
echo ""
|
|
23
|
+
echo "Then ask RafayGen to code anything:"
|
|
24
|
+
echo " rgcli ask \"build a simple python web server\""
|
|
25
|
+
echo ""
|
|
26
|
+
echo "For advanced users (Apt/Snap/Brew):"
|
|
27
|
+
echo " sudo snap install rgcli"
|
|
28
|
+
echo " sudo apt install rgcli"
|
|
29
|
+
echo " brew install rgcli"
|
|
30
|
+
echo "*(Native binary distribution coming soon via CI/CD pipelines)*"
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rafaygen-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"bin": {
|
|
14
|
+
"rgcli": "./bin/rgcli.js"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"axios": "^1.16.1",
|
|
18
|
+
"boxen": "^8.0.1",
|
|
19
|
+
"chalk": "^5.6.2",
|
|
20
|
+
"cli-highlight": "^2.1.11",
|
|
21
|
+
"commander": "^14.0.3",
|
|
22
|
+
"diff": "^9.0.0",
|
|
23
|
+
"inquirer": "^13.4.3",
|
|
24
|
+
"ora": "^9.4.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"esbuild": "^0.28.0",
|
|
28
|
+
"pkg": "^5.8.1"
|
|
29
|
+
},
|
|
30
|
+
"pkg": {
|
|
31
|
+
"scripts": [
|
|
32
|
+
"dist/bundle.cjs"
|
|
33
|
+
],
|
|
34
|
+
"targets": [
|
|
35
|
+
"node18-linux-x64",
|
|
36
|
+
"node18-macos-x64",
|
|
37
|
+
"node18-win-x64"
|
|
38
|
+
],
|
|
39
|
+
"outputPath": "binaries"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/pkg-config.json
ADDED
package/rgcli.deb
ADDED
|
Binary file
|
package/src/agent.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { getToken, getApiUrl } from "./auth.js";
|
|
2
|
+
import { renderBox, renderDiffBox, printError, printStep, printSuccess } from "./ui.js";
|
|
3
|
+
import inquirer from "inquirer";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { exec } from "child_process";
|
|
8
|
+
|
|
9
|
+
export async function askAgent(promptText) {
|
|
10
|
+
const token = getToken();
|
|
11
|
+
if (!token) {
|
|
12
|
+
printError("Not logged in. Please run 'rgcli login <token>' first.");
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
printStep("Connecting to RafayGen...");
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const res = await fetch(getApiUrl(), {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: {
|
|
22
|
+
"Content-Type": "application/json",
|
|
23
|
+
"Authorization": `Bearer ${token}`
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify({ prompt: promptText })
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
throw new Error(`API Error: ${res.statusText}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Since this is a simple implementation, we'll read the full JSON response.
|
|
33
|
+
// In a fully streaming CLI, you'd parse the stream.
|
|
34
|
+
const data = await res.json();
|
|
35
|
+
|
|
36
|
+
if (data.message) {
|
|
37
|
+
renderBox(" RafayGen ", data.message, "cyan");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (data.actions && data.actions.length > 0) {
|
|
41
|
+
for (const action of data.actions) {
|
|
42
|
+
await handleAction(action);
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
printSuccess("Done.");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
} catch (error) {
|
|
49
|
+
printError(error.message);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function handleAction(action) {
|
|
54
|
+
if (action.type === "write") {
|
|
55
|
+
const filepath = path.resolve(process.cwd(), action.file);
|
|
56
|
+
let original = "";
|
|
57
|
+
if (fs.existsSync(filepath)) {
|
|
58
|
+
original = fs.readFileSync(filepath, "utf-8");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Show diff
|
|
62
|
+
renderDiffBox(action.file, original, action.content);
|
|
63
|
+
|
|
64
|
+
// Ask user to confirm
|
|
65
|
+
const { confirm } = await inquirer.prompt([
|
|
66
|
+
{
|
|
67
|
+
type: "confirm",
|
|
68
|
+
name: "confirm",
|
|
69
|
+
message: `Allow RafayGen to write to ${action.file}?`,
|
|
70
|
+
default: true
|
|
71
|
+
}
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
if (confirm) {
|
|
75
|
+
fs.mkdirSync(path.dirname(filepath), { recursive: true });
|
|
76
|
+
fs.writeFileSync(filepath, action.content, "utf-8");
|
|
77
|
+
printSuccess(`Saved ${action.file}`);
|
|
78
|
+
} else {
|
|
79
|
+
console.log(chalk.yellow("Skipped write."));
|
|
80
|
+
}
|
|
81
|
+
} else if (action.type === "execute") {
|
|
82
|
+
renderBox(` Execute Command `, action.command, "magenta");
|
|
83
|
+
const { confirm } = await inquirer.prompt([
|
|
84
|
+
{
|
|
85
|
+
type: "confirm",
|
|
86
|
+
name: "confirm",
|
|
87
|
+
message: `Allow RafayGen to execute this command?`,
|
|
88
|
+
default: true
|
|
89
|
+
}
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
if (confirm) {
|
|
93
|
+
await new Promise((resolve) => {
|
|
94
|
+
const proc = exec(action.command, (err, stdout, stderr) => {
|
|
95
|
+
if (stdout) console.log(chalk.gray(stdout));
|
|
96
|
+
if (stderr) console.log(chalk.red(stderr));
|
|
97
|
+
if (err) printError(`Command failed with code ${err.code}`);
|
|
98
|
+
else printSuccess("Command executed successfully.");
|
|
99
|
+
resolve();
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
package/src/auth.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
|
|
5
|
+
const CONFIG_PATH = path.join(os.homedir(), ".rgcli.json");
|
|
6
|
+
|
|
7
|
+
export function loadConfig() {
|
|
8
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
9
|
+
try {
|
|
10
|
+
const data = fs.readFileSync(CONFIG_PATH, "utf-8");
|
|
11
|
+
return JSON.parse(data);
|
|
12
|
+
} catch (e) {
|
|
13
|
+
return {};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function saveConfig(config) {
|
|
20
|
+
const existing = loadConfig();
|
|
21
|
+
const updated = { ...existing, ...config };
|
|
22
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(updated, null, 2), "utf-8");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getToken() {
|
|
26
|
+
return loadConfig().token;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function setToken(token) {
|
|
30
|
+
saveConfig({ token });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function getApiUrl() {
|
|
34
|
+
// Default to localhost for local testing, can be overridden by environment variable or config
|
|
35
|
+
return process.env.RG_API_URL || loadConfig().apiUrl || "http://localhost:3000/api/cli";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function setApiUrl(apiUrl) {
|
|
39
|
+
saveConfig({ apiUrl });
|
|
40
|
+
}
|
package/src/ui.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import boxen from "boxen";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { highlight } from "cli-highlight";
|
|
4
|
+
import * as Diff from "diff";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
|
|
8
|
+
// Formats a message in a nice outlined box
|
|
9
|
+
export function renderBox(title, content, color = "cyan") {
|
|
10
|
+
const c = chalk[color] || chalk.cyan;
|
|
11
|
+
console.log(
|
|
12
|
+
boxen(content, {
|
|
13
|
+
title: c.bold(title),
|
|
14
|
+
titleAlignment: "left",
|
|
15
|
+
padding: 1,
|
|
16
|
+
margin: { top: 1, bottom: 1 },
|
|
17
|
+
borderStyle: "round",
|
|
18
|
+
borderColor: color,
|
|
19
|
+
})
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Renders syntax highlighted code in a box
|
|
24
|
+
export function renderCodeBox(filename, code, language = "typescript") {
|
|
25
|
+
const highlighted = highlight(code, {
|
|
26
|
+
language,
|
|
27
|
+
ignoreIllegals: true,
|
|
28
|
+
});
|
|
29
|
+
renderBox(` File: ${filename} `, highlighted, "blue");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Renders a git-like diff for code modifications
|
|
33
|
+
export function renderDiffBox(filename, original, modified) {
|
|
34
|
+
const diffResult = Diff.diffLines(original, modified);
|
|
35
|
+
let output = "";
|
|
36
|
+
|
|
37
|
+
diffResult.forEach((part) => {
|
|
38
|
+
// Add prefix and color based on diff status
|
|
39
|
+
let prefix = " ";
|
|
40
|
+
let colorize = chalk.dim;
|
|
41
|
+
|
|
42
|
+
if (part.added) {
|
|
43
|
+
prefix = chalk.green("+ ");
|
|
44
|
+
colorize = chalk.green;
|
|
45
|
+
} else if (part.removed) {
|
|
46
|
+
prefix = chalk.red("- ");
|
|
47
|
+
colorize = chalk.red;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Split part into lines and format
|
|
51
|
+
const lines = part.value.replace(/\n$/, "").split("\n");
|
|
52
|
+
lines.forEach((line) => {
|
|
53
|
+
output += colorize(`${prefix}${line}`) + "\n";
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
renderBox(` Diff: ${filename} `, output.trimEnd(), "yellow");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function printError(msg) {
|
|
61
|
+
console.log(chalk.red.bold("\n✖ Error: ") + chalk.red(msg) + "\n");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function printSuccess(msg) {
|
|
65
|
+
console.log(chalk.green.bold("\n✔ Success: ") + chalk.green(msg) + "\n");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function printStep(msg) {
|
|
69
|
+
console.log(chalk.cyan.bold("❯ ") + msg);
|
|
70
|
+
}
|