@riflo/ryte 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.
@@ -0,0 +1,21 @@
1
+ ## Description
2
+ Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context.
3
+
4
+ Fixes # (issue)
5
+
6
+ ## Type of Change
7
+ - [ ] Bug fix (non-breaking change which fixes an issue)
8
+ - [ ] New feature (non-breaking change which adds functionality)
9
+ - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
10
+ - [ ] Documentation update
11
+
12
+ ## How Has This Been Tested?
13
+ Please describe the tests that you ran to verify your changes.
14
+
15
+ ## Checklist:
16
+ - [ ] My code follows the style guidelines of this project
17
+ - [ ] I have performed a self-review of my own code
18
+ - [ ] I have commented my code, particularly in hard-to-understand areas
19
+ - [ ] I have made corresponding changes to the documentation
20
+ - [ ] My changes generate no new warnings
21
+ - [ ] I have committed using `pact c`
@@ -0,0 +1,38 @@
1
+ # Contributing to Pact-AI
2
+
3
+ First off, thank you for considering contributing to Pact-AI! It's people like you that make it a great tool.
4
+
5
+ ## Code of Conduct
6
+
7
+ By participating in this project, you agree to abide by our Code of Conduct (standard Contributor Covenant).
8
+
9
+ ## How Can I Contribute?
10
+
11
+ ### Reporting Bugs
12
+ - Use the GitHub issue tracker.
13
+ - Describe the bug and include steps to reproduce it.
14
+
15
+ ### Suggesting Enhancements
16
+ - Open an issue with the "enhancement" label.
17
+ - Explain why the feature would be useful.
18
+
19
+ ### Pull Requests
20
+ 1. Fork the repository.
21
+ 2. Create a new branch (`git checkout -b feature/amazing-feature`).
22
+ 3. Make your changes.
23
+ 4. **Important**: Use `pact c` to commit your changes. This helps us maintain a clean, semantic history.
24
+ 5. Push to the branch (`git push origin feature/amazing-feature`).
25
+ 6. Open a Pull Request.
26
+
27
+ ## Development Setup
28
+
29
+ 1. Clone your fork.
30
+ 2. Install dependencies: `npm install`.
31
+ 3. Link the package for local testing: `npm link`.
32
+ 4. Run with `pact`.
33
+
34
+ ## Style Guide
35
+ - Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification.
36
+ - Keep the code clean and well-documented.
37
+
38
+ Happy coding!
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Riflo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,228 @@
1
+ # RYTE
2
+
3
+ > **Write it right.** AI-powered Git workflow CLI for developers who care about clean history and velocity.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@riflo/ryte.svg?style=flat-square)](https://www.npmjs.com/package/@riflo/ryte)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
7
+ [![Node Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg?style=flat-square)](https://nodejs.org)
8
+
9
+ ---
10
+
11
+ ## Introduction
12
+
13
+ Writing meaningful commit messages and well-structured Pull Requests is critical for team collaboration, but it’s often a friction point in a fast-paced development cycle.
14
+
15
+ **ryte** is your CLI companion that bridge the gap between "coding" and "documenting". It reads your git diffs, understands the context of your changes, and generates professional, semantic-compliant messages in seconds.
16
+
17
+ ### Core Value
18
+ - **Zero Friction**: Stay in the terminal. No Web UI, no heavy extensions.
19
+ - **Semantic by Default**: Automatically follows [Conventional Commits](https://www.conventionalcommits.org/).
20
+ - **Intelligent Context**: Infers motivation from diffs and branch names.
21
+ - **Interactive Control**: You are always in charge with an `Accept/Edit/Regenerate` workflow.
22
+
23
+ ---
24
+
25
+ ## ⚑ Quick Start
26
+
27
+ ```bash
28
+ # 1. Install globally
29
+ npm install -g @riflo/ryte
30
+
31
+ # 2. Set your free AI key (get one at console.groq.com)
32
+ export GROQ_API_KEY="gsk_..."
33
+
34
+ # 3. Stage your changes and go
35
+ git add .
36
+ ryte c
37
+ ```
38
+
39
+ ---
40
+
41
+ ## The Problem It Solves
42
+
43
+ Your git log shouldn't look like this:
44
+ ```bash
45
+ ❌ update auth
46
+ ❌ fix bug
47
+ ❌ changes
48
+ ❌ wip
49
+ ```
50
+
51
+ With `ryte c`, it looks like this:
52
+ ```bash
53
+ βœ… feat(auth): implement JWT refresh token rotation
54
+ βœ… fix(cart): resolve crash on empty product array
55
+ βœ… refactor(db): extract query builder to repository layer
56
+ βœ… chore: update dependencies to remove security vulnerabilities
57
+ ```
58
+
59
+ One command. Same diff. Zero manual thinking.
60
+
61
+ ---
62
+
63
+ ## Installation
64
+
65
+ ### Via NPM (Recommended)
66
+ ```bash
67
+ npm install -g @riflo/ryte
68
+ ```
69
+
70
+ ### Via PNPM / Yarn
71
+ ```bash
72
+ pnpm add -g @riflo/ryte
73
+ # or
74
+ yarn global add @riflo/ryte
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Usage
80
+
81
+ ### 1. Generate Semantic Commit
82
+ Stage your files first, then let AI write the message.
83
+ ```bash
84
+ git add .
85
+ ryte c
86
+ ```
87
+ **Interactive Workflow:**
88
+ - `[A]ccept`: Applies the commit immediately.
89
+ - `[E]dit`: Opens your default editor (Vim/Notepad/Nano) to refine the message.
90
+ - `[R]egenerate`: Ask AI for another suggestion.
91
+ - `[C]ancel`: Abort the process.
92
+
93
+ ### 2. Generate PR Draft
94
+ Summarize your entire branch history into a clean Markdown description.
95
+ ```bash
96
+ ryte pr
97
+ ```
98
+ **Example Output:**
99
+ ```markdown
100
+ # πŸ”₯ Feat: User Authentication Flow
101
+
102
+ ## πŸ“‹ Summary
103
+ Introduces a complete JWT-based authentication system, including login, registration, and automatic token refresh via HTTP-only cookies.
104
+
105
+ ## πŸš€ Key Changes
106
+ - Implement `AuthMiddleware` for route protection
107
+ - Add `RefreshTokenRepository` for token rotation
108
+ - Create `LoginScreen` and `RegisterScreen` UI components
109
+
110
+ ## ⚠️ Important Notes/Impact
111
+ - **Requires DB Migration**: Run `php artisan migrate` for the new `personal_access_tokens` table.
112
+ - **Dependency Added**: Added `firebase/php-jwt` package.
113
+
114
+ ## πŸ” Reviewer Checklist
115
+ - [ ] Logic health & edge cases
116
+ - [ ] Performance considerations
117
+ - [ ] Code style & standard conformity
118
+ ```
119
+
120
+ ---
121
+
122
+ ## How It Works
123
+
124
+ 1. **Extraction**: Runs `git diff --staged` to capture your latest changes.
125
+ 2. **Analysis**: Filters out lockfiles and noise, then sends the core diff to high-performance AI models (Groq Llama 3 or OpenAI GPT-4o-mini).
126
+ 3. **Generation**: Crafts a semantic message (feat, fix, chore, etc.) based on the actual logic changes.
127
+ 4. **Interaction**: Presents a TUI (Terminal UI) for you to review and finalize the entry.
128
+
129
+ ---
130
+
131
+ ## Why Not Just Use GitHub Copilot?
132
+
133
+ Fair question. Here's an honest comparison:
134
+
135
+ | Feature | GitHub Copilot | **RYTE** |
136
+ |---|---|---|
137
+ | Works natively in terminal | ❌ | βœ… |
138
+ | Diff-aware (reads what you actually changed) | ❌ | βœ… |
139
+ | Enforces Conventional Commits format | ❌ | βœ… |
140
+ | No IDE required | ❌ | βœ… |
141
+ | Free tier available | ❌ | βœ… (via Groq) |
142
+ | BYOK (Bring Your Own Key) | ❌ | βœ… |
143
+
144
+ Copilot is great for writing code. RYTE is for **documenting the intent** behind it.
145
+
146
+ ---
147
+
148
+ ## πŸ”’ Security & Privacy
149
+
150
+ We understand that sending code to an external API is a sensitive decision. Here's exactly what RYTE does and does *not* do:
151
+
152
+ | What we send | What we do NOT send |
153
+ |---|---|
154
+ | `git diff --staged` output only | Full file contents |
155
+ | Truncated to max ~16k chars | Binary files |
156
+ | Nothing from untracked files | `.env` or secret files |
157
+
158
+ - βœ… No data is stored or logged by RYTE itself.
159
+ - βœ… Lockfiles (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`) are auto-excluded.
160
+ - βœ… Minified files (`*.min.js`, `*.min.css`) are auto-excluded.
161
+ - βœ… You can use your own API key (BYOK) for complete control over data flow.
162
+ - βœ… Supports local AI models via Ollama (on roadmap).
163
+
164
+ ---
165
+
166
+ ## Configuration
167
+
168
+ **ryte** requires an API key to function. We support two providers:
169
+
170
+ ### Groq (Recommended - Free & Instant)
171
+ Get your free key at [console.groq.com](https://console.groq.com/keys).
172
+ ```powershell
173
+ # Windows
174
+ $env:GROQ_API_KEY="gsk_..."
175
+
176
+ # Linux / Mac / Git Bash
177
+ export GROQ_API_KEY="gsk_..."
178
+ ```
179
+
180
+ ### OpenAI
181
+ Get your key at [platform.openai.com](https://platform.openai.com/api-keys).
182
+ ```bash
183
+ export OPENAI_API_KEY="sk-..."
184
+ ```
185
+
186
+ > [!TIP]
187
+ > Add these to your system environment variables to avoid setting them in every new session.
188
+
189
+ ---
190
+
191
+ ## Philosophy
192
+
193
+ We believe that **every commit should be written right**. A clean git history is not just about aesthetics; it's about debuggability, revertability, and understanding the "why" behind the code months after it was written.
194
+
195
+ ---
196
+
197
+ ## Roadmap
198
+
199
+ - [ ] **Context-Aware Radius**: Analyze importing files to suggest impact warnings.
200
+ - [ ] **JIRA / Linear / GitHub Issues**: Automatic ticket status sync.
201
+ - [ ] **Custom Rulesets**: Define your own commit linting rules for the AI.
202
+ - [ ] **Local LLM Support**: Support for Ollama/Llama.cpp for offline-only environments.
203
+
204
+ ---
205
+
206
+ Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
207
+
208
+ Please see [CONTRIBUTING.md](file:///d:/pact/CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests.
209
+
210
+ ---
211
+
212
+ ## License
213
+
214
+ Distributed under the MIT License. See [LICENSE](https://github.com/Rifuroo/ryte/blob/main/LICENSE) for more information.
215
+
216
+ ---
217
+
218
+ ## FAQ
219
+
220
+ **Q: Does it send my whole code to the AI?**
221
+ A: No. It only sends the `git diff` of your staged changes. It automatically ignores binary files and common lockfiles.
222
+
223
+ **Q: Is it free?**
224
+ A: The tool itself is free. If you use Groq, the API usage is currently free. If you use OpenAI, you pay for what you use (extremely cheap, ~$0.01 for dozens of commits).
225
+
226
+ ---
227
+
228
+ Developed with ❀️ by **Riflo**
package/bin/ryte.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../src/index.js";
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+
3
+ # Simple install script for pact CLI
4
+ echo "Installing PACT CLI globally..."
5
+ npm install -g .
6
+
7
+ echo ""
8
+ echo "Adding aliases to ~/.bashrc or ~/.zshrc is recommended:"
9
+ echo "alias c='pact c'"
10
+ echo "alias pr='pact pr'"
11
+ echo ""
12
+ echo "Don't forget to set OPENAI_API_KEY in your environment!"
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@riflo/ryte",
3
+ "version": "1.0.0",
4
+ "description": "AI Git Workflow Assistant - Generate semantic commits and PRs",
5
+ "main": "src/index.js",
6
+ "bin": {
7
+ "ryte": "bin/ryte.js"
8
+ },
9
+ "type": "module",
10
+ "keywords": [
11
+ "git",
12
+ "ai",
13
+ "commit",
14
+ "conventional-commits",
15
+ "workflow",
16
+ "automation"
17
+ ],
18
+ "author": "Riflo <rifloahmad@gmail.com>",
19
+ "license": "MIT",
20
+ "scripts": {
21
+ "start": "node bin/ryte.js"
22
+ },
23
+ "dependencies": {
24
+ "dotenv": "^16.4.5"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/Rifuroo/ryte.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/Rifuroo/ryte/issues"
32
+ },
33
+ "homepage": "https://github.com/Rifuroo/ryte#readme"
34
+ }
package/src/ai.js ADDED
@@ -0,0 +1,67 @@
1
+ import dotenv from "dotenv";
2
+ dotenv.config();
3
+
4
+ export async function generateAIResponse(messages) {
5
+ const groqKey = process.env.GROQ_API_KEY;
6
+ const openAiKey = process.env.OPENAI_API_KEY;
7
+
8
+ if (!groqKey && !openAiKey) {
9
+ console.error("Error: Please set either GROQ_API_KEY (for free AI) or OPENAI_API_KEY in your environment variables.");
10
+ process.exit(1);
11
+ }
12
+
13
+ const isGroq = !!groqKey;
14
+ const apiKey = isGroq ? groqKey : openAiKey;
15
+
16
+ // Groq API is 100% compatible with OpenAI's format! Just changing URL & Model.
17
+ const apiUrl = isGroq
18
+ ? "https://api.groq.com/openai/v1/chat/completions"
19
+ : "https://api.openai.com/v1/chat/completions";
20
+
21
+ // llama-3.1-8b-instant: 14,400 TPM (6x higher than llama-3.3-70b-versatile)
22
+ // Still very capable for commit messages and PR summaries
23
+ const model = isGroq
24
+ ? "llama-3.1-8b-instant"
25
+ : "gpt-4o-mini";
26
+
27
+ const MAX_RETRIES = 3;
28
+
29
+ for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
30
+ try {
31
+ const response = await fetch(apiUrl, {
32
+ method: "POST",
33
+ headers: {
34
+ "Content-Type": "application/json",
35
+ "Authorization": `Bearer ${apiKey}`
36
+ },
37
+ body: JSON.stringify({
38
+ model: model,
39
+ messages: messages,
40
+ temperature: 0.5,
41
+ })
42
+ });
43
+
44
+ if (response.status === 429) {
45
+ // Rate limited β€” parse retry-after header or use exponential backoff
46
+ const retryAfter = parseInt(response.headers.get("retry-after") || "15", 10);
47
+ const waitMs = (retryAfter + 1) * 1000;
48
+ console.warn(`\x1b[33m⚠ Rate limit hit. Waiting ${retryAfter + 1}s before retry (${attempt}/${MAX_RETRIES})...\x1b[0m`);
49
+ await new Promise(r => setTimeout(r, waitMs));
50
+ continue;
51
+ }
52
+
53
+ if (!response.ok) {
54
+ const error = await response.json();
55
+ throw new Error(error.error?.message || "API request failed");
56
+ }
57
+
58
+ const data = await response.json();
59
+ return data.choices[0].message.content.trim();
60
+ } catch (e) {
61
+ if (attempt === MAX_RETRIES) {
62
+ console.error("AI Generation failed:", e.message);
63
+ process.exit(1);
64
+ }
65
+ }
66
+ }
67
+ }
package/src/git.js ADDED
@@ -0,0 +1,68 @@
1
+ import { execSync } from "child_process";
2
+
3
+ export function getStagedDiff() {
4
+ try {
5
+ const diff = execSync(
6
+ 'git diff --staged -- . ' +
7
+ '":(exclude)package-lock.json" ' +
8
+ '":(exclude)pnpm-lock.yaml" ' +
9
+ '":(exclude)yarn.lock" ' +
10
+ '":(exclude)*.lock" ' +
11
+ '":(exclude)*.min.js" ' +
12
+ '":(exclude)*.min.css"',
13
+ { encoding: "utf-8" }
14
+ );
15
+
16
+ const trimmed = diff.trim();
17
+
18
+ // llama-3.1-8b-instant: 14,400 TPM. 1 token β‰ˆ 4 chars.
19
+ // Cap at ~16,000 chars (~4,000 tokens), leaving budget for the system prompt.
20
+ const MAX_CHARS = 16000;
21
+
22
+ if (trimmed.length > MAX_CHARS) {
23
+ console.warn(
24
+ `\x1b[33m⚠ Diff is large (${trimmed.length} chars). Truncating to fit AI token limit.\x1b[0m`
25
+ );
26
+ return trimmed.slice(0, MAX_CHARS) + "\n\n[... diff truncated to fit AI token limit ...]";
27
+ }
28
+
29
+ return trimmed;
30
+ } catch (e) {
31
+ console.error("Failed to get staged git diff. Are you in a git repository?");
32
+ process.exit(1);
33
+ }
34
+ }
35
+
36
+ export function getCurrentBranch() {
37
+ try {
38
+ const branch = execSync("git branch --show-current", { encoding: "utf-8" });
39
+ return branch.trim();
40
+ } catch (e) {
41
+ return "";
42
+ }
43
+ }
44
+
45
+ export function getBranchCommits(baseBranch = "main") {
46
+ try {
47
+ // get commits on current branch that are not on main
48
+ const commits = execSync(`git log ${baseBranch}..HEAD --oneline`, { encoding: "utf-8" });
49
+ return commits.trim();
50
+ } catch (e) {
51
+ // Fallback to latest 10 commits if main branch doesn't exist
52
+ try {
53
+ const commits = execSync(`git log -n 10 --oneline`, { encoding: "utf-8" });
54
+ return commits.trim();
55
+ } catch (err) {
56
+ return "";
57
+ }
58
+ }
59
+ }
60
+
61
+ export function applyCommit(message) {
62
+ try {
63
+ // write message to a temp file or pass via -m safely
64
+ execSync(`git commit -m ${JSON.stringify(message)}`, { stdio: "inherit" });
65
+ } catch (e) {
66
+ console.error("Failed to commit.");
67
+ }
68
+ }
package/src/index.js ADDED
@@ -0,0 +1,148 @@
1
+ import readline from "readline";
2
+ import { execSync } from "child_process";
3
+ import fs from "fs";
4
+ import os from "os";
5
+ import path from "path";
6
+ import { getStagedDiff, getCurrentBranch, getBranchCommits, applyCommit } from "./git.js";
7
+ import { generateAIResponse } from "./ai.js";
8
+ import { COMMIT_SYSTEM_PROMPT, PR_SYSTEM_PROMPT } from "./prompt.js";
9
+
10
+ const rl = readline.createInterface({
11
+ input: process.stdin,
12
+ output: process.stdout
13
+ });
14
+
15
+ async function question(query) {
16
+ return new Promise(resolve => rl.question(query, resolve));
17
+ }
18
+
19
+ // Ensure the user doesn't just hit enter for empty edits
20
+ function editInteractively(initialText) {
21
+ return new Promise((resolve) => {
22
+ const tmpFile = path.join(os.tmpdir(), `ryte_edit_${Date.now()}.txt`);
23
+ fs.writeFileSync(tmpFile, initialText, "utf-8");
24
+
25
+ const editor = process.env.EDITOR || "vim";
26
+ console.log(`\nOpening in ${editor}... Close the editor to save.`);
27
+ try {
28
+ execSync(`${editor} ${tmpFile}`, { stdio: "inherit" });
29
+ const result = fs.readFileSync(tmpFile, "utf-8").trim();
30
+ fs.unlinkSync(tmpFile);
31
+ resolve(result);
32
+ } catch (e) {
33
+ console.error("Editor closed with error.");
34
+ fs.unlinkSync(tmpFile);
35
+ resolve(initialText);
36
+ }
37
+ });
38
+ }
39
+
40
+ async function interactiveLoop(initialResult, type) {
41
+ let currentResult = initialResult;
42
+
43
+ while (true) {
44
+ console.log("\n" + "=".repeat(40));
45
+ console.log(`\x1b[36mSuggested ${type}:\x1b[0m\n`);
46
+ console.log(currentResult);
47
+ console.log("=".repeat(40) + "\n");
48
+
49
+ const answer = await question("Choose action: \x1b[32m[A]ccept\x1b[0m, \x1b[33m[E]dit\x1b[0m, \x1b[34m[R]egenerate\x1b[0m, \x1b[31m[C]ancel\x1b[0m : ");
50
+
51
+ const mode = answer.trim().toUpperCase();
52
+
53
+ if (mode === "A") {
54
+ return currentResult;
55
+ } else if (mode === "C") {
56
+ console.log("Cancelled.");
57
+ process.exit(0);
58
+ } else if (mode === "E") {
59
+ currentResult = await editInteractively(currentResult);
60
+ } else if (mode === "R") {
61
+ console.log("\nRegenerating...");
62
+ return "REGENERATE";
63
+ } else {
64
+ console.log("Invalid option. Please type A, E, R, or C.");
65
+ }
66
+ }
67
+ }
68
+
69
+ async function handleCommit() {
70
+ const diff = getStagedDiff();
71
+ if (!diff) {
72
+ console.log("No staged changes found. Use `git add` to stage files.");
73
+ process.exit(0);
74
+ }
75
+
76
+ const branch = getCurrentBranch();
77
+
78
+ while (true) {
79
+ console.log("\nAnalyzing staged diff...");
80
+ const result = await generateAIResponse([
81
+ { role: "system", content: COMMIT_SYSTEM_PROMPT },
82
+ { role: "user", content: `Branch: ${branch}\n\nDiff:\n${diff}` }
83
+ ]);
84
+
85
+ const finalAction = await interactiveLoop(result, "Commit Message");
86
+
87
+ if (finalAction !== "REGENERATE") {
88
+ applyCommit(finalAction);
89
+ console.log("\n\x1b[32mβœ” Commit applied successfully!\x1b[0m");
90
+ break;
91
+ }
92
+ }
93
+ }
94
+
95
+ async function handlePR() {
96
+ const commits = getBranchCommits();
97
+ if (!commits) {
98
+ console.log("No recent commits found distinct from main branch.");
99
+ process.exit(0);
100
+ }
101
+ const branch = getCurrentBranch();
102
+
103
+ while (true) {
104
+ console.log("\nAnalyzing recent commits...");
105
+ const result = await generateAIResponse([
106
+ { role: "system", content: PR_SYSTEM_PROMPT },
107
+ { role: "user", content: `Branch: ${branch}\n\nCommits:\n${commits}` }
108
+ ]);
109
+
110
+ const finalAction = await interactiveLoop(result, "PR Markdown Description");
111
+
112
+ if (finalAction !== "REGENERATE") {
113
+ console.log("\n\x1b[32mFinal PR Content:\x1b[0m\n");
114
+ console.log(finalAction);
115
+ console.log("\n(You can copy-paste the above into your pull request or we can pipe it to the clipboard later)");
116
+ break;
117
+ }
118
+ }
119
+ }
120
+
121
+ async function main() {
122
+ const args = process.argv.slice(2);
123
+ const cmd = args[0]?.toLowerCase();
124
+
125
+ if (cmd === "c" || cmd === "commit") {
126
+ await handleCommit();
127
+ } else if (cmd === "pr") {
128
+ await handlePR();
129
+ } else {
130
+ console.log(`
131
+ \x1b[36mRYTE - AI Git Workflow Assistant\x1b[0m
132
+ Author: Riflo
133
+
134
+ Usage:
135
+ ryte c Generate semantic commit from staged diff
136
+ ryte pr Generate PR markdown description from branch commits
137
+
138
+ Set GROQ_API_KEY (Free) or OPENAI_API_KEY environment variable.
139
+ `);
140
+ }
141
+
142
+ rl.close();
143
+ }
144
+
145
+ main().catch(err => {
146
+ console.error("Unhandled error:", err);
147
+ process.exit(1);
148
+ });
package/src/prompt.js ADDED
@@ -0,0 +1,52 @@
1
+ export const COMMIT_SYSTEM_PROMPT = `
2
+ You are an expert developer assistant specialized in Git workflows and the Conventional Commits specification.
3
+ Your goal is to generate a concise, meaningful, and technically accurate commit message based on provided git diffs.
4
+
5
+ RULES:
6
+ 1. OUTPUT ONLY THE COMMIT MESSAGE. No markdown, no "Here is your commit", no backticks.
7
+ 2. Follow Conventional Commits: <type>(<scope>): <subject>
8
+ 3. Use types: feat (new feature), fix (bug fix), docs (documentation), style (formatting), refactor (code cleanup), perf (performance), test (adding tests), chore (maintenance).
9
+ 4. Subject line:
10
+ - Use imperative mood ("add", not "adds" or "added").
11
+ - Max 50 characters.
12
+ - Do not end with a period.
13
+ - Focus on the "why" or the core "what", not every trivial change.
14
+ 5. Breaking Changes: If the diff shows breaking changes, use "!" after the type (e.g., "feat!: delete deprecated api").
15
+ 6. Scope: If the diff is localized, infer a scope (e.g., "auth", "ui", "config").
16
+ 7. Body (Optional): If the change is complex, add a brief body after 1 blank line to explain technical nuances.
17
+ 8. Context: If a branch name or ticket is provided, incorporate it into the scope or footer if applicable.
18
+
19
+ Example:
20
+ feat(ui): add loading state to checkout button
21
+ `;
22
+
23
+ export const PR_SYSTEM_PROMPT = `
24
+ You are a technical writer for a high-performing engineering team.
25
+ Write a clear, professional Pull Request summary based on the provided commit history and branch context.
26
+
27
+ OUTPUT STRUCTURE:
28
+ # <Brief & Punchy PR Title>
29
+
30
+ ## πŸ“‹ Summary
31
+ Provide a high-level overview (2-3 sentences) of what this PR solves. Focus on the value to the project.
32
+
33
+ ## πŸš€ Key Changes
34
+ - List the most important technical changes in bullet points.
35
+ - Group related changes if possible.
36
+ - Highlight any refactoring or performance improvements.
37
+
38
+ ## ⚠️ Important Notes/Impact
39
+ - Mention any database migrations, new dependencies, or potential breaking changes.
40
+ - If no critical impact, state "Standard incremental update".
41
+
42
+ ## πŸ” Reviewer Checklist
43
+ - [ ] Logic health & edge cases
44
+ - [ ] Performance considerations
45
+ - [ ] Code style & standard conformity
46
+
47
+ INSTRUCTIONS:
48
+ - Use clean Markdown.
49
+ - DO NOT use markdown code block wrappers ( \`\`\` ) for the whole output.
50
+ - Be objective and technical.
51
+ - No conversational filler.
52
+ `;