@rotorsoft/gent 1.26.0 → 1.26.1
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/README.md +36 -0
- package/dist/{chunk-XBUSPWBB.js → chunk-6CFTGBMW.js} +228 -1
- package/dist/chunk-6CFTGBMW.js.map +1 -0
- package/dist/{chunk-FML3SVK5.js → chunk-ALH7P5G7.js} +2 -2
- package/dist/{chunk-SBG4BMMM.js → chunk-ZJCC7PIU.js} +2 -2
- package/dist/github-remote-YCNZHVOB.js +9 -0
- package/dist/index.js +62 -133
- package/dist/index.js.map +1 -1
- package/dist/setup-labels-FNGDKJX7.js +9 -0
- package/package.json +1 -1
- package/dist/chunk-XBUSPWBB.js.map +0 -1
- package/dist/github-remote-GJIXMSQK.js +0 -9
- package/dist/setup-labels-3IV5GAOW.js +0 -9
- /package/dist/{chunk-FML3SVK5.js.map → chunk-ALH7P5G7.js.map} +0 -0
- /package/dist/{chunk-SBG4BMMM.js.map → chunk-ZJCC7PIU.js.map} +0 -0
- /package/dist/{github-remote-GJIXMSQK.js.map → github-remote-YCNZHVOB.js.map} +0 -0
- /package/dist/{setup-labels-3IV5GAOW.js.map → setup-labels-FNGDKJX7.js.map} +0 -0
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# @rotorsoft/gent
|
|
2
2
|
|
|
3
|
+
[](https://github.com/Rotorsoft/gent/actions/workflows/ci.yml) [](https://github.com/Rotorsoft/gent/actions/workflows/release.yml) [](https://www.npmjs.com/package/@rotorsoft/gent) [](https://www.npmjs.com/package/@rotorsoft/gent) [](https://github.com/Rotorsoft/gent/blob/main/LICENSE) [](https://nodejs.org)
|
|
4
|
+
|
|
3
5
|
AI-powered GitHub workflow tool - leverage AI (Claude, Gemini, or Codex) to create tickets, implement features, and manage PRs from an interactive dashboard.
|
|
4
6
|
|
|
5
7
|
|
|
@@ -510,6 +512,40 @@ gent create "Fix auth"
|
|
|
510
512
|
- Validation commands
|
|
511
513
|
- Branch naming preferences
|
|
512
514
|
|
|
515
|
+
3. **Customize AI prompts** — override any built-in prompt:
|
|
516
|
+
```bash
|
|
517
|
+
# Generate .gent-prompts.yml with all defaults as a reference
|
|
518
|
+
gent init --prompts
|
|
519
|
+
```
|
|
520
|
+
Then uncomment and edit any prompt in `.gent-prompts.yml`. Templates use `{variable}` syntax for interpolation — dynamic values are replaced at runtime while your custom wording is preserved.
|
|
521
|
+
|
|
522
|
+
Available prompt keys and their variables:
|
|
523
|
+
|
|
524
|
+
| Key | Purpose | Variables |
|
|
525
|
+
|-----|---------|-----------|
|
|
526
|
+
| `ticket` | Issue creation | `{description}`, `{agent_instructions_section}`, `{additional_hints_section}` |
|
|
527
|
+
| `implementation` | Code implementation | `{issue_number}`, `{issue_title}`, `{issue_body}`, `{validation_commands}`, `{provider_name}`, `{provider_email}`, `{progress_file}` |
|
|
528
|
+
| `pr` | PR description | `{issue_section}`, `{commits}`, `{diff_summary}`, `{close_reference}` |
|
|
529
|
+
| `commit` | Interactive commit | `{issue_context}`, `{provider_name}`, `{provider_email}` |
|
|
530
|
+
| `commit_message` | Commit message | `{issue_context}`, `{diff}` |
|
|
531
|
+
| `pr_video` | Video capture | `{max_duration}` |
|
|
532
|
+
|
|
533
|
+
Example override in `.gent-prompts.yml`:
|
|
534
|
+
```yaml
|
|
535
|
+
implementation: |
|
|
536
|
+
Issue #{issue_number}: {issue_title}
|
|
537
|
+
|
|
538
|
+
{issue_body}
|
|
539
|
+
|
|
540
|
+
{agent_instructions_section}
|
|
541
|
+
## Instructions
|
|
542
|
+
1. Implement the feature
|
|
543
|
+
2. Add tests
|
|
544
|
+
3. Run validation:
|
|
545
|
+
{validation_commands}
|
|
546
|
+
4. Commit with: Co-Authored-By: {provider_name} <{provider_email}>
|
|
547
|
+
```
|
|
548
|
+
|
|
513
549
|
### Handling AI Blocks
|
|
514
550
|
|
|
515
551
|
If the AI gets stuck (`ai-blocked` label):
|
|
@@ -88,6 +88,174 @@ var colors = {
|
|
|
88
88
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
89
89
|
import { join } from "path";
|
|
90
90
|
import { parse as parseYaml } from "yaml";
|
|
91
|
+
|
|
92
|
+
// src/lib/default-prompts.ts
|
|
93
|
+
var DEFAULT_PROMPTS = {
|
|
94
|
+
ticket: `You are creating a GitHub issue for a software project following an AI-assisted development workflow.
|
|
95
|
+
|
|
96
|
+
User Request: {description}
|
|
97
|
+
|
|
98
|
+
{agent_instructions_section}{additional_hints_section}
|
|
99
|
+
Create a detailed GitHub issue following this exact template.
|
|
100
|
+
|
|
101
|
+
IMPORTANT: Start your output IMMEDIATELY with "TITLE:" followed by a clear, concise issue title in imperative mood (e.g., "Add OAuth2 authentication for Google and GitHub"). Keep titles under 100 characters when possible. Then on the next line, start with "## Description". Do not include any preamble, commentary, or introduction.
|
|
102
|
+
|
|
103
|
+
TITLE: [Clear, concise issue title in imperative mood]
|
|
104
|
+
|
|
105
|
+
## Description
|
|
106
|
+
[Clear user-facing description of what needs to be done]
|
|
107
|
+
|
|
108
|
+
## Technical Context
|
|
109
|
+
**Type:** feature | fix | refactor | chore | docs | test
|
|
110
|
+
**Category:** ui | api | database | workers | shared | testing | infra
|
|
111
|
+
**Priority:** critical | high | medium | low
|
|
112
|
+
**Risk:** low | medium | high
|
|
113
|
+
|
|
114
|
+
### Architecture Notes
|
|
115
|
+
- [Relevant patterns to follow]
|
|
116
|
+
- [Related systems affected]
|
|
117
|
+
- [Constraints or invariants]
|
|
118
|
+
|
|
119
|
+
## Implementation Steps
|
|
120
|
+
- [ ] Step 1: Specific technical task
|
|
121
|
+
- [ ] Step 2: Specific technical task
|
|
122
|
+
- [ ] Step 3: Specific technical task
|
|
123
|
+
|
|
124
|
+
## Testing Requirements
|
|
125
|
+
- **Unit tests:** [What to test]
|
|
126
|
+
- **Integration tests:** [What to test if applicable]
|
|
127
|
+
- **Manual verification:** [What to check]
|
|
128
|
+
|
|
129
|
+
## Acceptance Criteria
|
|
130
|
+
- [ ] Criterion 1
|
|
131
|
+
- [ ] Criterion 2
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
IMPORTANT: After the issue content, on a new line, output ONLY the following metadata in this exact format:
|
|
135
|
+
META:type=<type>,priority=<priority>,risk=<risk>,area=<area>
|
|
136
|
+
|
|
137
|
+
Example: META:type=feature,priority=high,risk=low,area=ui`,
|
|
138
|
+
implementation: `GitHub Issue #{issue_number}: {issue_title}
|
|
139
|
+
|
|
140
|
+
{issue_body}
|
|
141
|
+
|
|
142
|
+
{agent_instructions_section}{progress_section}{extra_context_section}
|
|
143
|
+
## Your Task
|
|
144
|
+
|
|
145
|
+
1. **Implement the feature/fix** following patterns from the project's AGENT.md or codebase conventions
|
|
146
|
+
2. **Add unit tests** for any new functionality
|
|
147
|
+
3. **Run validation** before committing:
|
|
148
|
+
{validation_commands}
|
|
149
|
+
4. **Make an atomic commit** with a clear message following conventional commits format:
|
|
150
|
+
- Use format: <type>: <description>
|
|
151
|
+
- Include "Completed GitHub issue #{issue_number}" in body
|
|
152
|
+
- End with: Co-Authored-By: {provider_name} <{provider_email}>
|
|
153
|
+
5. **Update {progress_file}** - append a compact entry documenting your work:
|
|
154
|
+
[YYYY-MM-DD] #{issue_number} <type>: <brief description>
|
|
155
|
+
- Files: <comma-separated list of changed files>
|
|
156
|
+
- Changes: <1-2 sentence summary of what was implemented>
|
|
157
|
+
- Decisions: <key technical decisions made, if any>
|
|
158
|
+
- Issues: <concerns or follow-ups for reviewers, if any>
|
|
159
|
+
Keep entries minimal (4-6 lines max). Skip sections if not applicable.
|
|
160
|
+
6. **Do NOT push** - the user will review and push manually
|
|
161
|
+
|
|
162
|
+
Focus on clean, minimal implementation. Don't over-engineer.`,
|
|
163
|
+
pr: `Generate a pull request description for the following changes.
|
|
164
|
+
|
|
165
|
+
{issue_section}
|
|
166
|
+
## Commits
|
|
167
|
+
{commits}
|
|
168
|
+
|
|
169
|
+
## Changed Files
|
|
170
|
+
{diff_summary}
|
|
171
|
+
|
|
172
|
+
Generate a PR description in this format:
|
|
173
|
+
|
|
174
|
+
## Summary
|
|
175
|
+
- [1-3 bullet points summarizing the changes]
|
|
176
|
+
|
|
177
|
+
## Test Plan
|
|
178
|
+
- [ ] [Testing steps]
|
|
179
|
+
|
|
180
|
+
{close_reference}
|
|
181
|
+
|
|
182
|
+
Only output the PR description, nothing else.`,
|
|
183
|
+
commit_message: `Generate a concise git commit message for the following changes.
|
|
184
|
+
{issue_context}
|
|
185
|
+
## Diff
|
|
186
|
+
{diff}
|
|
187
|
+
|
|
188
|
+
Rules:
|
|
189
|
+
- Use conventional commit format: <type>: <short description>
|
|
190
|
+
- Types: feat, fix, refactor, chore, docs, test, style, perf
|
|
191
|
+
- Keep the first line under 72 characters
|
|
192
|
+
- Do NOT include a body or footer
|
|
193
|
+
- Output ONLY the commit message, nothing else`,
|
|
194
|
+
commit: `Create a git commit for the staged changes.
|
|
195
|
+
|
|
196
|
+
Context: {issue_context}
|
|
197
|
+
|
|
198
|
+
Steps:
|
|
199
|
+
1. Run \`git diff --cached --stat\` to see what files changed
|
|
200
|
+
2. Run \`git diff --cached\` to see the actual changes
|
|
201
|
+
3. Generate a commit message following these rules:
|
|
202
|
+
- Use conventional commit format: <type>: <short description>
|
|
203
|
+
- Types: feat, fix, refactor, chore, docs, test, style, perf
|
|
204
|
+
- Keep the first line under 72 characters
|
|
205
|
+
- Add a blank line, then: Co-Authored-By: {provider_name} <{provider_email}>
|
|
206
|
+
4. Run \`git commit -m "<your message>"\` to create the commit
|
|
207
|
+
5. Exit when done
|
|
208
|
+
|
|
209
|
+
Do not ask for confirmation - just create the commit.`,
|
|
210
|
+
video: `You are helping capture a Playwright video demonstration of UI changes for GitHub Issue #{issue_number}: {issue_title}
|
|
211
|
+
|
|
212
|
+
{agent_instructions_section}
|
|
213
|
+
## Task: Record UI Demo Video
|
|
214
|
+
|
|
215
|
+
Create a short video (max {max_duration}s) demonstrating the UI changes made for this issue.
|
|
216
|
+
|
|
217
|
+
### Video Requirements
|
|
218
|
+
- Resolution: {width}x{height}
|
|
219
|
+
- Format: WebM or MP4
|
|
220
|
+
- Duration: Under {max_duration} seconds
|
|
221
|
+
- Show the key UI interactions and visual changes
|
|
222
|
+
|
|
223
|
+
### Steps
|
|
224
|
+
|
|
225
|
+
1. **Start the development server** if not already running
|
|
226
|
+
2. **Use Playwright to record video** of the relevant UI interactions:
|
|
227
|
+
- Navigate to the affected pages/components
|
|
228
|
+
- Demonstrate the new or changed functionality
|
|
229
|
+
- Show before/after if applicable
|
|
230
|
+
|
|
231
|
+
3. **Upload video to GitHub** as a release asset or use GitHub's drag-drop upload:
|
|
232
|
+
- Create a GitHub release or upload to issue comments
|
|
233
|
+
- Get the permanent URL for the video
|
|
234
|
+
- Do NOT commit video files to the repository
|
|
235
|
+
|
|
236
|
+
4. **Add video to PR** by commenting with the video URL or embedding it
|
|
237
|
+
|
|
238
|
+
### Important
|
|
239
|
+
- Upload video to GitHub assets, NOT to the repository
|
|
240
|
+
- Keep the video concise - focus on demonstrating the changes
|
|
241
|
+
- Ensure the video clearly shows the UI improvements
|
|
242
|
+
|
|
243
|
+
Output the GitHub URL where the video was uploaded when complete.`,
|
|
244
|
+
pr_video: `
|
|
245
|
+
IMPORTANT: This PR contains UI changes. Use the Playwright MCP plugin to:
|
|
246
|
+
1. Start the dev server if needed
|
|
247
|
+
2. Navigate to the relevant pages showing the UI changes
|
|
248
|
+
3. Capture a short demo video (max {max_duration}s) showcasing the changes
|
|
249
|
+
4. Upload the video to GitHub and include it in the PR description under a "## Demo Video" section
|
|
250
|
+
`
|
|
251
|
+
};
|
|
252
|
+
function interpolate(template, variables) {
|
|
253
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => {
|
|
254
|
+
return key in variables ? variables[key] : match;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/lib/config.ts
|
|
91
259
|
var runtimeProvider = null;
|
|
92
260
|
function setRuntimeProvider(provider) {
|
|
93
261
|
runtimeProvider = provider;
|
|
@@ -152,6 +320,20 @@ function getAgentPath(cwd = process.cwd()) {
|
|
|
152
320
|
const agentPath = join(cwd, config.claude.agent_file);
|
|
153
321
|
return existsSync(agentPath) ? agentPath : null;
|
|
154
322
|
}
|
|
323
|
+
function getPromptsFilePath(cwd = process.cwd()) {
|
|
324
|
+
return join(cwd, ".gent-prompts.yml");
|
|
325
|
+
}
|
|
326
|
+
function loadPromptsFile(cwd) {
|
|
327
|
+
const promptsPath = getPromptsFilePath(cwd);
|
|
328
|
+
if (!existsSync(promptsPath)) return {};
|
|
329
|
+
try {
|
|
330
|
+
const content = readFileSync(promptsPath, "utf-8");
|
|
331
|
+
const parsed = parseYaml(content);
|
|
332
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
333
|
+
} catch {
|
|
334
|
+
return {};
|
|
335
|
+
}
|
|
336
|
+
}
|
|
155
337
|
function loadConfig(cwd = process.cwd()) {
|
|
156
338
|
const configPath = getConfigPath(cwd);
|
|
157
339
|
if (!existsSync(configPath)) {
|
|
@@ -165,6 +347,14 @@ function loadConfig(cwd = process.cwd()) {
|
|
|
165
347
|
return DEFAULT_CONFIG;
|
|
166
348
|
}
|
|
167
349
|
}
|
|
350
|
+
function getPrompt(key, variables, cwd = process.cwd()) {
|
|
351
|
+
const overrides = loadPromptsFile(cwd);
|
|
352
|
+
const template = overrides[key] ?? DEFAULT_PROMPTS[key];
|
|
353
|
+
if (!template) {
|
|
354
|
+
throw new Error(`Unknown prompt key: ${key}`);
|
|
355
|
+
}
|
|
356
|
+
return interpolate(template, variables);
|
|
357
|
+
}
|
|
168
358
|
function loadAgentInstructions(cwd = process.cwd()) {
|
|
169
359
|
const agentPath = getAgentPath(cwd);
|
|
170
360
|
if (!agentPath) {
|
|
@@ -313,6 +503,40 @@ validation:
|
|
|
313
503
|
- "npm run test"
|
|
314
504
|
`;
|
|
315
505
|
}
|
|
506
|
+
function generateDefaultPromptsFile() {
|
|
507
|
+
const variableDocs = {
|
|
508
|
+
ticket: `# Variables: {description}, {agent_instructions_section}, {additional_hints_section}`,
|
|
509
|
+
implementation: `# Variables: {issue_number}, {issue_title}, {issue_body}, {agent_instructions_section},
|
|
510
|
+
# {progress_section}, {extra_context_section}, {validation_commands},
|
|
511
|
+
# {provider_name}, {provider_email}, {progress_file}`,
|
|
512
|
+
pr: `# Variables: {issue_section}, {commits}, {diff_summary}, {close_reference}`,
|
|
513
|
+
commit_message: `# Variables: {issue_context}, {diff}`,
|
|
514
|
+
commit: `# Variables: {issue_context}, {provider_name}, {provider_email}`,
|
|
515
|
+
video: `# Variables: {issue_number}, {issue_title}, {agent_instructions_section},
|
|
516
|
+
# {max_duration}, {width}, {height}`,
|
|
517
|
+
pr_video: `# Variables: {max_duration}`
|
|
518
|
+
};
|
|
519
|
+
let output = `# Gent Prompt Templates
|
|
520
|
+
# Override any prompt by uncommenting and editing it.
|
|
521
|
+
# Templates use {variable_name} syntax for interpolation.
|
|
522
|
+
# See https://github.com/rotorsoft/gent for documentation
|
|
523
|
+
`;
|
|
524
|
+
for (const [key, template] of Object.entries(DEFAULT_PROMPTS)) {
|
|
525
|
+
const docs = variableDocs[key] || "";
|
|
526
|
+
output += `
|
|
527
|
+
# --- ${key} ---
|
|
528
|
+
`;
|
|
529
|
+
if (docs) output += `${docs}
|
|
530
|
+
`;
|
|
531
|
+
output += `# ${key}: |
|
|
532
|
+
`;
|
|
533
|
+
for (const line of template.split("\n")) {
|
|
534
|
+
output += `# ${line}
|
|
535
|
+
`;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return output;
|
|
539
|
+
}
|
|
316
540
|
|
|
317
541
|
// src/utils/validators.ts
|
|
318
542
|
import { execa } from "execa";
|
|
@@ -836,10 +1060,13 @@ export {
|
|
|
836
1060
|
setRuntimeProvider,
|
|
837
1061
|
resolveProvider,
|
|
838
1062
|
getConfigPath,
|
|
1063
|
+
getPromptsFilePath,
|
|
839
1064
|
loadConfig,
|
|
1065
|
+
getPrompt,
|
|
840
1066
|
loadAgentInstructions,
|
|
841
1067
|
configExists,
|
|
842
1068
|
generateDefaultConfig,
|
|
1069
|
+
generateDefaultPromptsFile,
|
|
843
1070
|
checkGhAuth,
|
|
844
1071
|
checkClaudeCli,
|
|
845
1072
|
checkGeminiCli,
|
|
@@ -884,4 +1111,4 @@ export {
|
|
|
884
1111
|
remoteBranchExists,
|
|
885
1112
|
fetchAndCheckout
|
|
886
1113
|
};
|
|
887
|
-
//# sourceMappingURL=chunk-
|
|
1114
|
+
//# sourceMappingURL=chunk-6CFTGBMW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts","../src/lib/config.ts","../src/lib/default-prompts.ts","../src/utils/validators.ts","../src/lib/github.ts","../src/lib/git.ts"],"sourcesContent":["import chalk from \"chalk\";\n\n// eslint-disable-next-line no-control-regex\nconst stripAnsi = (str: string) => str.replace(/\\x1b\\[[0-9;]*m/g, \"\");\nconst visibleLength = (str: string) => stripAnsi(str).length;\n\nexport interface TableEntry {\n key: string;\n value: string;\n}\n\nexport const logger = {\n info: (message: string) => console.log(chalk.blue(\"ℹ\"), message),\n success: (message: string) => console.log(chalk.green(\"✓\"), message),\n warning: (message: string) => console.log(chalk.yellow(\"⚠\"), message),\n error: (message: string) => console.log(chalk.red(\"✗\"), message),\n debug: (message: string) => {\n if (process.env.DEBUG) {\n console.log(chalk.gray(\"⋯\"), message);\n }\n },\n dim: (message: string) => console.log(chalk.dim(message)),\n bold: (message: string) => console.log(chalk.bold(message)),\n highlight: (message: string) => console.log(chalk.cyan(message)),\n\n /**\n * Display a bordered table with key-value pairs.\n * Used for operation summaries before AI invocation.\n */\n table: (title: string, entries: TableEntry[]) => {\n // Filter out entries with empty values\n const validEntries = entries.filter((e) => e.value);\n if (validEntries.length === 0) return;\n\n // Calculate column widths\n const keyWidth = Math.max(...validEntries.map((e) => e.key.length));\n const valueWidth = Math.max(\n ...validEntries.map((e) => visibleLength(e.value))\n );\n const innerWidth = Math.max(title.length, keyWidth + valueWidth + 3); // 3 = \" : \"\n const totalWidth = innerWidth + 4; // 4 = \"│ \" + \" │\"\n\n // Pad string to target length accounting for ANSI codes\n const padVisible = (str: string, len: number) => {\n const visible = visibleLength(str);\n return str + \" \".repeat(Math.max(0, len - visible));\n };\n\n // Render\n console.log(chalk.dim(\"┌\" + \"─\".repeat(totalWidth - 2) + \"┐\"));\n console.log(\n `${chalk.dim(\"│\")} ${chalk.bold.cyan(title.padEnd(innerWidth))} ${chalk.dim(\"│\")}`\n );\n console.log(chalk.dim(\"├\" + \"─\".repeat(totalWidth - 2) + \"┤\"));\n for (const { key, value } of validEntries) {\n const row = chalk.dim(key.padEnd(keyWidth)) + \" \" + value;\n console.log(\n `${chalk.dim(\"│\")} ${padVisible(row, innerWidth)} ${chalk.dim(\"│\")}`\n );\n }\n console.log(chalk.dim(\"└\" + \"─\".repeat(totalWidth - 2) + \"┘\"));\n },\n\n box: (title: string, content: string) => {\n const lines = content.split(\"\\n\");\n // Calculate visible length (strips ANSI codes) for proper alignment\n const maxLen =\n Math.max(title.length, ...lines.map((l) => visibleLength(l))) + 4;\n const border = \"─\".repeat(maxLen);\n\n // Pad string to target length accounting for ANSI codes\n const padVisible = (str: string, len: number) => {\n const visible = visibleLength(str);\n return str + \" \".repeat(Math.max(0, len - visible));\n };\n\n console.log(chalk.dim(`┌${border}┐`));\n console.log(\n `${chalk.dim(\"│\")} ${chalk.bold(title.padEnd(maxLen - 2))} ${chalk.dim(\"│\")}`\n );\n console.log(chalk.dim(`├${border}┤`));\n for (const line of lines) {\n console.log(\n `${chalk.dim(\"│\")} ${padVisible(line, maxLen - 2)} ${chalk.dim(\"│\")}`\n );\n }\n console.log(chalk.dim(`└${border}┘`));\n },\n\n list: (items: string[], bullet = \"•\") => {\n for (const item of items) {\n console.log(chalk.dim(bullet), item);\n }\n },\n\n newline: () => console.log(),\n};\n\nexport const colors = {\n issue: chalk.cyan,\n branch: chalk.magenta,\n label: chalk.yellow,\n file: chalk.green,\n command: chalk.blue,\n url: chalk.underline.blue,\n provider: chalk.cyan.bold,\n};\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { GentConfig, AIProvider } from \"../types/index.js\";\nimport { DEFAULT_PROMPTS, interpolate } from \"./default-prompts.js\";\n\n// Module-level variable to hold runtime provider override (e.g. from TUI)\nlet runtimeProvider: AIProvider | null = null;\n\nexport function setRuntimeProvider(provider: AIProvider): void {\n runtimeProvider = provider;\n}\n\n/**\n * Helper to resolve the active provider based on precedence:\n * 1. CLI options (explicit flag)\n * 2. Runtime override (in-memory state)\n * 3. Environment variable (GENT_AI_PROVIDER)\n * 4. Configuration (file)\n * 5. Default\n */\nexport function resolveProvider(\n options: { provider?: AIProvider } | undefined,\n config: GentConfig\n): AIProvider {\n return options?.provider ?? config.ai.provider;\n}\n\nconst DEFAULT_CONFIG: GentConfig = {\n version: 1,\n github: {\n labels: {\n workflow: {\n ready: \"ai-ready\",\n in_progress: \"ai-in-progress\",\n completed: \"ai-completed\",\n blocked: \"ai-blocked\",\n },\n types: [\"feature\", \"fix\", \"refactor\", \"chore\", \"docs\", \"test\"],\n priorities: [\"critical\", \"high\", \"medium\", \"low\"],\n risks: [\"low\", \"medium\", \"high\"],\n areas: [\"ui\", \"api\", \"database\", \"workers\", \"shared\", \"testing\", \"infra\"],\n },\n },\n branch: {\n pattern: \"{author}/{type}-{issue}-{slug}\",\n author_source: \"git\",\n author_env_var: \"GENT_AUTHOR\",\n },\n progress: {\n file: \"progress.txt\",\n archive_threshold: 500,\n archive_dir: \".gent/archive\",\n },\n claude: {\n permission_mode: \"acceptEdits\",\n agent_file: \"AGENT.md\",\n },\n gemini: {\n sandbox_mode: \"on\",\n agent_file: \"AGENT.md\",\n },\n codex: {\n agent_file: \"AGENT.md\",\n },\n ai: {\n provider: \"claude\",\n auto_fallback: true,\n },\n video: {\n enabled: true,\n max_duration: 30,\n width: 1280,\n height: 720,\n },\n validation: [\"npm run typecheck\", \"npm run lint\", \"npm run test\"],\n};\n\nexport function getConfigPath(cwd: string = process.cwd()): string {\n return join(cwd, \".gent.yml\");\n}\n\nexport function getAgentPath(cwd: string = process.cwd()): string | null {\n const config = loadConfig(cwd);\n // Use claude.agent_file for backward compatibility\n const agentPath = join(cwd, config.claude.agent_file);\n return existsSync(agentPath) ? agentPath : null;\n}\n\nexport function getPromptsFilePath(cwd: string = process.cwd()): string {\n return join(cwd, \".gent-prompts.yml\");\n}\n\nfunction loadPromptsFile(cwd: string): Record<string, string> {\n const promptsPath = getPromptsFilePath(cwd);\n if (!existsSync(promptsPath)) return {};\n try {\n const content = readFileSync(promptsPath, \"utf-8\");\n const parsed = parseYaml(content);\n return parsed && typeof parsed === \"object\" ? (parsed as Record<string, string>) : {};\n } catch {\n return {};\n }\n}\n\nexport function loadConfig(cwd: string = process.cwd()): GentConfig {\n const configPath = getConfigPath(cwd);\n\n if (!existsSync(configPath)) {\n return DEFAULT_CONFIG;\n }\n\n try {\n const content = readFileSync(configPath, \"utf-8\");\n const userConfig = parseYaml(content) as Partial<GentConfig>;\n\n return mergeConfig(DEFAULT_CONFIG, userConfig);\n } catch {\n return DEFAULT_CONFIG;\n }\n}\n\n/**\n * Get a prompt template by key, with user overrides from .gent-prompts.yml\n * merged over defaults. Performs variable interpolation on the result.\n */\nexport function getPrompt(\n key: string,\n variables: Record<string, string>,\n cwd: string = process.cwd()\n): string {\n const overrides = loadPromptsFile(cwd);\n const template = overrides[key] ?? DEFAULT_PROMPTS[key];\n if (!template) {\n throw new Error(`Unknown prompt key: ${key}`);\n }\n return interpolate(template, variables);\n}\n\nexport function loadAgentInstructions(\n cwd: string = process.cwd()\n): string | null {\n const agentPath = getAgentPath(cwd);\n\n if (!agentPath) {\n return null;\n }\n\n try {\n return readFileSync(agentPath, \"utf-8\");\n } catch {\n return null;\n }\n}\n\nexport function configExists(cwd: string = process.cwd()): boolean {\n return existsSync(getConfigPath(cwd));\n}\n\nfunction mergeConfig(\n defaults: GentConfig,\n user: Partial<GentConfig>\n): GentConfig {\n // Support GENT_AI_PROVIDER environment variable override\n const envProvider = process.env.GENT_AI_PROVIDER as\n | \"claude\"\n | \"gemini\"\n | \"codex\"\n | undefined;\n\n // Runtime override takes precedence over env var\n const effectiveProvider = runtimeProvider ?? envProvider;\n\n return {\n version: user.version ?? defaults.version,\n github: {\n labels: {\n workflow: {\n ...defaults.github.labels.workflow,\n ...user.github?.labels?.workflow,\n },\n types: user.github?.labels?.types ?? defaults.github.labels.types,\n priorities:\n user.github?.labels?.priorities ?? defaults.github.labels.priorities,\n risks: user.github?.labels?.risks ?? defaults.github.labels.risks,\n areas: user.github?.labels?.areas ?? defaults.github.labels.areas,\n },\n },\n branch: {\n ...defaults.branch,\n ...user.branch,\n },\n progress: {\n ...defaults.progress,\n ...user.progress,\n },\n claude: {\n ...defaults.claude,\n ...user.claude,\n },\n gemini: {\n ...defaults.gemini,\n ...user.gemini,\n },\n codex: {\n ...defaults.codex,\n ...user.codex,\n },\n ai: {\n ...defaults.ai,\n ...user.ai,\n // Runtime/Env takes precedence\n ...(effectiveProvider && { provider: effectiveProvider }),\n },\n video: {\n ...defaults.video,\n ...user.video,\n },\n validation: user.validation ?? defaults.validation,\n };\n}\n\nexport function updateConfigProvider(\n provider: AIProvider,\n cwd: string = process.cwd()\n): void {\n const configPath = getConfigPath(cwd);\n if (!existsSync(configPath)) {\n writeFileSync(configPath, generateDefaultConfig(provider), \"utf-8\");\n return;\n }\n const content = readFileSync(configPath, \"utf-8\");\n const updated = content.replace(\n /^(\\s*provider:\\s*)\"[^\"]*\"/m,\n `$1\"${provider}\"`\n );\n writeFileSync(configPath, updated, \"utf-8\");\n}\n\nexport function generateDefaultConfig(provider: AIProvider = \"claude\"): string {\n return `# Gent Configuration\n# See https://github.com/rotorsoft/gent for documentation\nversion: 1\n\n# GitHub settings\ngithub:\n labels:\n workflow:\n ready: \"ai-ready\"\n in_progress: \"ai-in-progress\"\n completed: \"ai-completed\"\n blocked: \"ai-blocked\"\n types:\n - feature\n - fix\n - refactor\n - chore\n - docs\n - test\n priorities:\n - critical\n - high\n - medium\n - low\n risks:\n - low\n - medium\n - high\n areas:\n - ui\n - api\n - database\n - workers\n - shared\n - testing\n - infra\n\n# Branch naming convention\nbranch:\n pattern: \"{author}/{type}-{issue}-{slug}\"\n author_source: \"git\" # git | env | prompt\n author_env_var: \"GENT_AUTHOR\"\n\n# Progress tracking\nprogress:\n file: \"progress.txt\"\n archive_threshold: 500\n archive_dir: \".gent/archive\"\n\n# Claude settings\nclaude:\n permission_mode: \"acceptEdits\"\n agent_file: \"AGENT.md\"\n\n# Gemini settings\ngemini:\n sandbox_mode: \"on\"\n agent_file: \"AGENT.md\"\n\n# Codex settings\ncodex:\n agent_file: \"AGENT.md\"\n\n# AI provider settings\nai:\n provider: \"${provider}\" # claude | gemini | codex\n # fallback_provider: \"gemini\" # optional fallback when rate limited\n auto_fallback: true # automatically switch to fallback on rate limit\n\n# Video capture for UI changes (requires Playwright)\nvideo:\n enabled: true # set to false to disable video capture for PRs with UI changes\n max_duration: 30 # maximum video duration in seconds\n width: 1280 # video width\n height: 720 # video height\n\n# Validation commands (run before commit)\nvalidation:\n - \"npm run typecheck\"\n - \"npm run lint\"\n - \"npm run test\"\n`;\n}\n\n/**\n * Generate a .gent-prompts.yml file with all built-in prompt templates.\n * Each prompt is documented with its available variables.\n */\nexport function generateDefaultPromptsFile(): string {\n const variableDocs: Record<string, string> = {\n ticket: `# Variables: {description}, {agent_instructions_section}, {additional_hints_section}`,\n implementation: `# Variables: {issue_number}, {issue_title}, {issue_body}, {agent_instructions_section},\n# {progress_section}, {extra_context_section}, {validation_commands},\n# {provider_name}, {provider_email}, {progress_file}`,\n pr: `# Variables: {issue_section}, {commits}, {diff_summary}, {close_reference}`,\n commit_message: `# Variables: {issue_context}, {diff}`,\n commit: `# Variables: {issue_context}, {provider_name}, {provider_email}`,\n video: `# Variables: {issue_number}, {issue_title}, {agent_instructions_section},\n# {max_duration}, {width}, {height}`,\n pr_video: `# Variables: {max_duration}`,\n };\n\n let output = `# Gent Prompt Templates\n# Override any prompt by uncommenting and editing it.\n# Templates use {variable_name} syntax for interpolation.\n# See https://github.com/rotorsoft/gent for documentation\n`;\n\n for (const [key, template] of Object.entries(DEFAULT_PROMPTS)) {\n const docs = variableDocs[key] || \"\";\n output += `\\n# --- ${key} ---\\n`;\n if (docs) output += `${docs}\\n`;\n output += `# ${key}: |\\n`;\n for (const line of template.split(\"\\n\")) {\n output += `# ${line}\\n`;\n }\n }\n\n return output;\n}\n","/**\n * Default prompt templates for all AI interactions.\n * Users can override any prompt via .gent.yml (prompts section) or .gent-prompts.yml.\n * Templates use {variable_name} syntax for interpolation.\n */\n\nexport const DEFAULT_PROMPTS: Record<string, string> = {\n ticket: `You are creating a GitHub issue for a software project following an AI-assisted development workflow.\n\nUser Request: {description}\n\n{agent_instructions_section}{additional_hints_section}\nCreate a detailed GitHub issue following this exact template.\n\nIMPORTANT: Start your output IMMEDIATELY with \"TITLE:\" followed by a clear, concise issue title in imperative mood (e.g., \"Add OAuth2 authentication for Google and GitHub\"). Keep titles under 100 characters when possible. Then on the next line, start with \"## Description\". Do not include any preamble, commentary, or introduction.\n\nTITLE: [Clear, concise issue title in imperative mood]\n\n## Description\n[Clear user-facing description of what needs to be done]\n\n## Technical Context\n**Type:** feature | fix | refactor | chore | docs | test\n**Category:** ui | api | database | workers | shared | testing | infra\n**Priority:** critical | high | medium | low\n**Risk:** low | medium | high\n\n### Architecture Notes\n- [Relevant patterns to follow]\n- [Related systems affected]\n- [Constraints or invariants]\n\n## Implementation Steps\n- [ ] Step 1: Specific technical task\n- [ ] Step 2: Specific technical task\n- [ ] Step 3: Specific technical task\n\n## Testing Requirements\n- **Unit tests:** [What to test]\n- **Integration tests:** [What to test if applicable]\n- **Manual verification:** [What to check]\n\n## Acceptance Criteria\n- [ ] Criterion 1\n- [ ] Criterion 2\n\n---\nIMPORTANT: After the issue content, on a new line, output ONLY the following metadata in this exact format:\nMETA:type=<type>,priority=<priority>,risk=<risk>,area=<area>\n\nExample: META:type=feature,priority=high,risk=low,area=ui`,\n\n implementation: `GitHub Issue #{issue_number}: {issue_title}\n\n{issue_body}\n\n{agent_instructions_section}{progress_section}{extra_context_section}\n## Your Task\n\n1. **Implement the feature/fix** following patterns from the project's AGENT.md or codebase conventions\n2. **Add unit tests** for any new functionality\n3. **Run validation** before committing:\n{validation_commands}\n4. **Make an atomic commit** with a clear message following conventional commits format:\n - Use format: <type>: <description>\n - Include \"Completed GitHub issue #{issue_number}\" in body\n - End with: Co-Authored-By: {provider_name} <{provider_email}>\n5. **Update {progress_file}** - append a compact entry documenting your work:\n [YYYY-MM-DD] #{issue_number} <type>: <brief description>\n - Files: <comma-separated list of changed files>\n - Changes: <1-2 sentence summary of what was implemented>\n - Decisions: <key technical decisions made, if any>\n - Issues: <concerns or follow-ups for reviewers, if any>\n Keep entries minimal (4-6 lines max). Skip sections if not applicable.\n6. **Do NOT push** - the user will review and push manually\n\nFocus on clean, minimal implementation. Don't over-engineer.`,\n\n pr: `Generate a pull request description for the following changes.\n\n{issue_section}\n## Commits\n{commits}\n\n## Changed Files\n{diff_summary}\n\nGenerate a PR description in this format:\n\n## Summary\n- [1-3 bullet points summarizing the changes]\n\n## Test Plan\n- [ ] [Testing steps]\n\n{close_reference}\n\nOnly output the PR description, nothing else.`,\n\n commit_message: `Generate a concise git commit message for the following changes.\n{issue_context}\n## Diff\n{diff}\n\nRules:\n- Use conventional commit format: <type>: <short description>\n- Types: feat, fix, refactor, chore, docs, test, style, perf\n- Keep the first line under 72 characters\n- Do NOT include a body or footer\n- Output ONLY the commit message, nothing else`,\n\n commit: `Create a git commit for the staged changes.\n\nContext: {issue_context}\n\nSteps:\n1. Run \\`git diff --cached --stat\\` to see what files changed\n2. Run \\`git diff --cached\\` to see the actual changes\n3. Generate a commit message following these rules:\n - Use conventional commit format: <type>: <short description>\n - Types: feat, fix, refactor, chore, docs, test, style, perf\n - Keep the first line under 72 characters\n - Add a blank line, then: Co-Authored-By: {provider_name} <{provider_email}>\n4. Run \\`git commit -m \"<your message>\"\\` to create the commit\n5. Exit when done\n\nDo not ask for confirmation - just create the commit.`,\n\n video: `You are helping capture a Playwright video demonstration of UI changes for GitHub Issue #{issue_number}: {issue_title}\n\n{agent_instructions_section}\n## Task: Record UI Demo Video\n\nCreate a short video (max {max_duration}s) demonstrating the UI changes made for this issue.\n\n### Video Requirements\n- Resolution: {width}x{height}\n- Format: WebM or MP4\n- Duration: Under {max_duration} seconds\n- Show the key UI interactions and visual changes\n\n### Steps\n\n1. **Start the development server** if not already running\n2. **Use Playwright to record video** of the relevant UI interactions:\n - Navigate to the affected pages/components\n - Demonstrate the new or changed functionality\n - Show before/after if applicable\n\n3. **Upload video to GitHub** as a release asset or use GitHub's drag-drop upload:\n - Create a GitHub release or upload to issue comments\n - Get the permanent URL for the video\n - Do NOT commit video files to the repository\n\n4. **Add video to PR** by commenting with the video URL or embedding it\n\n### Important\n- Upload video to GitHub assets, NOT to the repository\n- Keep the video concise - focus on demonstrating the changes\n- Ensure the video clearly shows the UI improvements\n\nOutput the GitHub URL where the video was uploaded when complete.`,\n\n pr_video: `\nIMPORTANT: This PR contains UI changes. Use the Playwright MCP plugin to:\n1. Start the dev server if needed\n2. Navigate to the relevant pages showing the UI changes\n3. Capture a short demo video (max {max_duration}s) showcasing the changes\n4. Upload the video to GitHub and include it in the PR description under a \"## Demo Video\" section\n`,\n};\n\n/**\n * Interpolate variables in a prompt template.\n * Replaces {variable_name} with corresponding values.\n * Unresolved variables are left as-is.\n */\nexport function interpolate(\n template: string,\n variables: Record<string, string>\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key) => {\n return key in variables ? variables[key] : match;\n });\n}\n","import { execa } from \"execa\";\nimport type { GentConfig, AIProvider } from \"../types/index.js\";\nimport { configExists } from \"../lib/config.js\";\n\nexport async function checkGhCli(): Promise<boolean> {\n try {\n await execa(\"gh\", [\"--version\"]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function checkGhAuth(): Promise<boolean> {\n try {\n await execa(\"gh\", [\"auth\", \"status\"]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function checkClaudeCli(): Promise<boolean> {\n try {\n await execa(\"claude\", [\"--version\"]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function checkGeminiCli(): Promise<boolean> {\n try {\n await execa(\"gemini\", [\"--version\"]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function checkCodexCLI(): Promise<boolean> {\n try {\n await execa(\"codex\", [\"--version\"]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function checkAIProvider(provider: AIProvider): Promise<boolean> {\n switch (provider) {\n case \"claude\":\n return checkClaudeCli();\n case \"gemini\":\n return checkGeminiCli();\n case \"codex\":\n return checkCodexCLI();\n }\n}\n\nexport async function checkGitRepo(): Promise<boolean> {\n try {\n await execa(\"git\", [\"rev-parse\", \"--git-dir\"]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function validatePrerequisites(config?: GentConfig): Promise<{\n valid: boolean;\n missing: string[];\n}> {\n const checks = [\n { name: \"gh CLI\", check: checkGhCli },\n { name: \"gh auth\", check: checkGhAuth },\n { name: \"git repository\", check: checkGitRepo },\n ];\n\n const getProviderName = (provider: AIProvider) => {\n switch (provider) {\n case \"claude\":\n return \"claude CLI\";\n case \"gemini\":\n return \"gemini CLI\";\n case \"codex\":\n return \"codex CLI\";\n }\n };\n\n // Add AI provider check based on config\n if (config) {\n const provider = config.ai.provider;\n checks.push({\n name: getProviderName(provider),\n check: () => checkAIProvider(provider),\n });\n\n // Also check fallback if configured\n if (config.ai.fallback_provider) {\n const fallback = config.ai.fallback_provider;\n checks.push({\n name: `${getProviderName(fallback)} (fallback)`,\n check: () => checkAIProvider(fallback),\n });\n }\n } else {\n // Default to checking claude for backward compatibility\n checks.push({ name: \"claude CLI\", check: checkClaudeCli });\n }\n\n const missing: string[] = [];\n\n for (const { name, check } of checks) {\n const passed = await check();\n if (!passed) {\n missing.push(name);\n }\n }\n\n return {\n valid: missing.length === 0,\n missing,\n };\n}\n\nexport function checkInitialized(cwd?: string): boolean {\n return configExists(cwd);\n}\n\nexport function isValidIssueNumber(value: string): boolean {\n const num = parseInt(value, 10);\n return !isNaN(num) && num > 0;\n}\n\nexport function sanitizeSlug(title: string, maxLength = 40): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, maxLength);\n}\n","import { execa } from \"execa\";\nimport type {\n GitHubIssue,\n GitHubLabel,\n GitHubReviewData,\n} from \"../types/index.js\";\n\nconst WORKFLOW_LABELS = [\n \"ai-ready\",\n \"ai-in-progress\",\n \"ai-completed\",\n \"ai-blocked\",\n];\n\nexport async function checkLabelsExist(): Promise<boolean> {\n try {\n const { stdout } = await execa(\"gh\", [\n \"label\",\n \"list\",\n \"--json\",\n \"name\",\n \"--limit\",\n \"200\",\n ]);\n const labels: { name: string }[] = JSON.parse(stdout);\n const names = new Set(labels.map((l) => l.name));\n return WORKFLOW_LABELS.every((wl) => names.has(wl));\n } catch {\n return false;\n }\n}\n\nexport async function getIssue(issueNumber: number): Promise<GitHubIssue> {\n const { stdout } = await execa(\"gh\", [\n \"issue\",\n \"view\",\n String(issueNumber),\n \"--json\",\n \"number,title,body,labels,state,assignees,url\",\n ]);\n\n const data = JSON.parse(stdout);\n return {\n number: data.number,\n title: data.title,\n body: data.body || \"\",\n labels: data.labels.map((l: { name: string }) => l.name),\n state: data.state.toLowerCase(),\n assignee: data.assignees?.[0]?.login,\n url: data.url,\n };\n}\n\nexport async function listIssues(options: {\n labels?: string[];\n state?: \"open\" | \"closed\" | \"all\";\n limit?: number;\n}): Promise<GitHubIssue[]> {\n const args = [\n \"issue\",\n \"list\",\n \"--json\",\n \"number,title,body,labels,state,url\",\n ];\n\n if (options.labels?.length) {\n args.push(\"--label\", options.labels.join(\",\"));\n }\n\n if (options.state) {\n args.push(\"--state\", options.state);\n }\n\n args.push(\"--limit\", String(options.limit || 50));\n\n const { stdout } = await execa(\"gh\", args);\n const data = JSON.parse(stdout);\n\n return data.map(\n (d: {\n number: number;\n title: string;\n body: string;\n labels: { name: string }[];\n state: string;\n url: string;\n }) => ({\n number: d.number,\n title: d.title,\n body: d.body || \"\",\n labels: d.labels.map((l) => l.name),\n state: d.state.toLowerCase() as \"open\" | \"closed\",\n url: d.url,\n })\n );\n}\n\nexport async function createIssue(options: {\n title: string;\n body: string;\n labels?: string[];\n}): Promise<number> {\n const args = [\n \"issue\",\n \"create\",\n \"--title\",\n options.title,\n \"--body\",\n options.body,\n ];\n\n if (options.labels?.length) {\n args.push(\"--label\", options.labels.join(\",\"));\n }\n\n const { stdout } = await execa(\"gh\", args);\n\n // Extract issue number from URL\n const match = stdout.match(/\\/issues\\/(\\d+)/);\n if (!match) {\n throw new Error(\"Failed to extract issue number from gh output\");\n }\n\n return parseInt(match[1], 10);\n}\n\nexport async function updateIssueLabels(\n issueNumber: number,\n options: {\n add?: string[];\n remove?: string[];\n }\n): Promise<void> {\n const promises: Promise<unknown>[] = [];\n\n if (options.add?.length) {\n promises.push(\n execa(\"gh\", [\n \"issue\",\n \"edit\",\n String(issueNumber),\n \"--add-label\",\n options.add.join(\",\"),\n ])\n );\n }\n\n if (options.remove?.length) {\n promises.push(\n execa(\"gh\", [\n \"issue\",\n \"edit\",\n String(issueNumber),\n \"--remove-label\",\n options.remove.join(\",\"),\n ])\n );\n }\n\n await Promise.all(promises);\n}\n\nexport async function addIssueComment(\n issueNumber: number,\n body: string\n): Promise<void> {\n await execa(\"gh\", [\"issue\", \"comment\", String(issueNumber), \"--body\", body]);\n}\n\nexport async function assignIssue(\n issueNumber: number,\n assignee: string\n): Promise<void> {\n await execa(\"gh\", [\n \"issue\",\n \"edit\",\n String(issueNumber),\n \"--add-assignee\",\n assignee,\n ]);\n}\n\nexport async function createLabel(label: GitHubLabel): Promise<void> {\n try {\n await execa(\"gh\", [\n \"label\",\n \"create\",\n label.name,\n \"--color\",\n label.color,\n \"--description\",\n label.description || \"\",\n \"--force\",\n ]);\n } catch {\n // Label might already exist, ignore error\n }\n}\n\nexport async function createPullRequest(options: {\n title: string;\n body: string;\n base?: string;\n draft?: boolean;\n}): Promise<string> {\n const args = [\n \"pr\",\n \"create\",\n \"--title\",\n options.title,\n \"--body\",\n options.body,\n \"--assignee\",\n \"@me\",\n ];\n\n if (options.base) {\n args.push(\"--base\", options.base);\n }\n\n if (options.draft) {\n args.push(\"--draft\");\n }\n\n const { stdout } = await execa(\"gh\", args);\n return stdout.trim();\n}\n\nexport interface PrBasicInfo {\n number: number;\n url: string;\n}\n\nexport interface PrStatusInfo {\n number: number;\n title: string;\n url: string;\n state: \"open\" | \"closed\" | \"merged\";\n reviewDecision: string | null;\n isDraft: boolean;\n}\n\nexport async function getPrForBranch(): Promise<PrBasicInfo | null> {\n try {\n const { stdout } = await execa(\"gh\", [\n \"pr\",\n \"view\",\n \"--json\",\n \"number,url\",\n ]);\n const data = JSON.parse(stdout);\n return { number: data.number, url: data.url };\n } catch {\n return null;\n }\n}\n\nexport async function getPrStatus(): Promise<PrStatusInfo | null> {\n try {\n const { stdout } = await execa(\"gh\", [\n \"pr\",\n \"view\",\n \"--json\",\n \"number,title,url,state,reviewDecision,isDraft\",\n ]);\n const data = JSON.parse(stdout);\n // gh pr view returns state as OPEN, CLOSED, or MERGED (uppercase)\n const state = (data.state?.toLowerCase() ?? \"open\") as\n | \"open\"\n | \"closed\"\n | \"merged\";\n return {\n number: data.number,\n title: data.title ?? \"\",\n url: data.url,\n state,\n reviewDecision: data.reviewDecision ?? null,\n isDraft: data.isDraft ?? false,\n };\n } catch {\n return null;\n }\n}\n\nexport async function getPrReviewData(\n prNumber?: number\n): Promise<GitHubReviewData> {\n // Fetch reviews and comments using gh pr view (both are supported JSON fields)\n const prArgs = [\"pr\", \"view\"];\n if (prNumber) {\n prArgs.push(String(prNumber));\n }\n prArgs.push(\"--json\", \"reviews,comments\");\n\n const { stdout: prStdout } = await execa(\"gh\", prArgs);\n const prData = JSON.parse(prStdout);\n\n // Fetch review threads using GraphQL API (not available via gh pr view --json)\n // First get repo owner and name since GraphQL doesn't support {owner}/{repo} placeholders\n let reviewThreads: Array<{\n isResolved?: boolean | null;\n isOutdated?: boolean;\n path?: string;\n line?: number | null;\n comments: Array<{\n author: string;\n body: string;\n path?: string;\n line?: number | null;\n createdAt?: string;\n }>;\n }> = [];\n\n try {\n const { stdout: repoStdout } = await execa(\"gh\", [\n \"repo\",\n \"view\",\n \"--json\",\n \"owner,name\",\n ]);\n const repoData = JSON.parse(repoStdout);\n const owner = repoData.owner?.login ?? repoData.owner;\n const repo = repoData.name;\n\n const graphqlQuery = `query { repository(owner: \"${owner}\", name: \"${repo}\") { pullRequest(number: ${prNumber}) { reviewThreads(first: 100) { nodes { isResolved isOutdated path line comments(first: 100) { nodes { databaseId author { login } body path line createdAt } } } } } } }`;\n\n const { stdout: graphqlStdout } = await execa(\"gh\", [\n \"api\",\n \"graphql\",\n \"-f\",\n `query=${graphqlQuery}`,\n ]);\n const graphqlData = JSON.parse(graphqlStdout);\n const prNode = graphqlData.data?.repository?.pullRequest;\n const threadNodes = prNode?.reviewThreads?.nodes ?? [];\n\n reviewThreads = threadNodes.map(\n (thread: {\n isResolved?: boolean | null;\n isOutdated?: boolean;\n path?: string;\n line?: number | null;\n comments?: {\n nodes?: Array<{\n databaseId?: number;\n author?: { login?: string };\n body?: string;\n path?: string;\n line?: number | null;\n createdAt?: string;\n }>;\n };\n }) => ({\n isResolved: thread.isResolved ?? null,\n isOutdated: thread.isOutdated ?? false,\n path: thread.path,\n line: thread.line ?? null,\n comments: (thread.comments?.nodes ?? []).map((comment) => ({\n id: comment.databaseId,\n author: comment.author?.login ?? \"unknown\",\n body: comment.body ?? \"\",\n path: comment.path ?? thread.path,\n line: comment.line ?? thread.line ?? null,\n createdAt: comment.createdAt,\n })),\n })\n );\n } catch {\n // If GraphQL fails (e.g., no permissions), continue with empty threads\n reviewThreads = [];\n }\n\n return {\n reviews: (prData.reviews ?? []).map(\n (review: {\n author?: { login?: string };\n body?: string;\n state?: string;\n submittedAt?: string;\n }) => ({\n author: review.author?.login ?? \"unknown\",\n body: review.body ?? \"\",\n state: review.state ?? \"UNKNOWN\",\n submittedAt: review.submittedAt,\n })\n ),\n reviewThreads,\n comments: (prData.comments ?? []).map(\n (comment: {\n id?: string;\n author?: { login?: string };\n body?: string;\n createdAt?: string;\n }) => ({\n id: comment.id,\n author: comment.author?.login ?? \"unknown\",\n body: comment.body ?? \"\",\n createdAt: comment.createdAt,\n })\n ),\n };\n}\n\nexport async function getCurrentUser(): Promise<string> {\n const { stdout } = await execa(\"gh\", [\"api\", \"user\", \"--jq\", \".login\"]);\n return stdout.trim();\n}\n\nexport async function replyToReviewComment(\n prNumber: number,\n commentId: number,\n body: string\n): Promise<void> {\n await execa(\"gh\", [\n \"api\",\n `repos/{owner}/{repo}/pulls/${prNumber}/comments/${commentId}/replies`,\n \"-f\",\n `body=${body}`,\n ]);\n}\n\nexport async function addPrComment(\n prNumber: number,\n body: string\n): Promise<void> {\n await execa(\"gh\", [\"pr\", \"comment\", String(prNumber), \"--body\", body]);\n}\n\nexport interface OpenPr {\n number: number;\n title: string;\n headRefName: string;\n url: string;\n}\n\nexport async function listOpenPrs(limit: number = 30): Promise<OpenPr[]> {\n const { stdout } = await execa(\"gh\", [\n \"pr\",\n \"list\",\n \"--state\",\n \"open\",\n \"--json\",\n \"number,title,headRefName,url\",\n \"--limit\",\n String(limit),\n ]);\n const data = JSON.parse(stdout);\n return data.map(\n (d: {\n number: number;\n title: string;\n headRefName: string;\n url: string;\n }) => ({\n number: d.number,\n title: d.title,\n headRefName: d.headRefName,\n url: d.url,\n })\n );\n}\n","import { execa } from \"execa\";\nimport { configExists } from \"./config.js\";\nimport { checkLabelsExist } from \"./github.js\";\n\nexport interface RepoSetupState {\n gitInitialized: boolean;\n gentInitialized: boolean;\n hasRemote: boolean;\n hasLabels: boolean;\n}\n\nexport async function getRepoSetupState(): Promise<RepoSetupState> {\n // Step 1: Check git init\n let gitInitialized = false;\n try {\n await execa(\"git\", [\"rev-parse\", \"--git-dir\"]);\n gitInitialized = true;\n } catch {\n return { gitInitialized: false, gentInitialized: false, hasRemote: false, hasLabels: false };\n }\n\n // Step 2: Check gent config\n const gentInitialized = configExists();\n\n // Step 3: Check remote\n let hasRemote = false;\n try {\n const { stdout } = await execa(\"git\", [\"config\", \"--get\", \"remote.origin.url\"]);\n hasRemote = stdout.trim().length > 0;\n } catch {\n // No remote\n }\n if (!hasRemote) {\n return { gitInitialized, gentInitialized, hasRemote: false, hasLabels: false };\n }\n\n // Step 4: Check labels\n const hasLabels = await checkLabelsExist().catch(() => false);\n\n return { gitInitialized, gentInitialized, hasRemote, hasLabels };\n}\n\nexport async function getCurrentBranch(): Promise<string> {\n const { stdout } = await execa(\"git\", [\"branch\", \"--show-current\"]);\n return stdout.trim();\n}\n\nexport async function isOnMainBranch(): Promise<boolean> {\n const branch = await getCurrentBranch();\n return branch === \"main\" || branch === \"master\";\n}\n\nexport async function getDefaultBranch(): Promise<string> {\n try {\n const { stdout } = await execa(\"git\", [\n \"symbolic-ref\",\n \"refs/remotes/origin/HEAD\",\n ]);\n return stdout.trim().replace(\"refs/remotes/origin/\", \"\");\n } catch {\n // Fallback to checking if main or master exists\n try {\n await execa(\"git\", [\"rev-parse\", \"--verify\", \"main\"]);\n return \"main\";\n } catch {\n return \"master\";\n }\n }\n}\n\nexport async function branchExists(name: string): Promise<boolean> {\n try {\n await execa(\"git\", [\"rev-parse\", \"--verify\", name]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function createBranch(name: string, from?: string): Promise<void> {\n if (from) {\n await execa(\"git\", [\"checkout\", \"-b\", name, from]);\n } else {\n await execa(\"git\", [\"checkout\", \"-b\", name]);\n }\n}\n\nexport async function checkoutBranch(name: string): Promise<void> {\n await execa(\"git\", [\"checkout\", name]);\n}\n\nexport async function hasUncommittedChanges(): Promise<boolean> {\n const { stdout } = await execa(\"git\", [\"status\", \"--porcelain\"]);\n return stdout.trim().length > 0;\n}\n\nexport async function getUnpushedCommits(): Promise<boolean> {\n try {\n const { stdout } = await execa(\"git\", [\"log\", \"@{u}..HEAD\", \"--oneline\"]);\n return stdout.trim().length > 0;\n } catch {\n // No upstream set\n return true;\n }\n}\n\nexport async function pushBranch(branch?: string): Promise<void> {\n const branchName = branch || (await getCurrentBranch());\n await execa(\"git\", [\"push\", \"-u\", \"origin\", branchName]);\n}\n\nexport async function getAuthorInitials(): Promise<string> {\n // Try git config user.initials first\n try {\n const { stdout } = await execa(\"git\", [\"config\", \"user.initials\"]);\n if (stdout.trim()) {\n return stdout.trim();\n }\n } catch {\n // Not set, continue\n }\n\n // Fall back to deriving from user.name\n try {\n const { stdout } = await execa(\"git\", [\"config\", \"user.name\"]);\n const name = stdout.trim();\n if (name) {\n // Extract initials from name (e.g., \"John Doe\" -> \"jd\")\n const parts = name.split(/\\s+/);\n return parts.map((p) => p[0]?.toLowerCase() || \"\").join(\"\");\n }\n } catch {\n // Not set\n }\n\n return \"dev\";\n}\n\nexport async function getRepoInfo(): Promise<{\n owner: string;\n repo: string;\n} | null> {\n try {\n const { stdout } = await execa(\"git\", [\n \"config\",\n \"--get\",\n \"remote.origin.url\",\n ]);\n const url = stdout.trim();\n\n // Handle SSH format: git@github.com:owner/repo.git\n const sshMatch = url.match(/git@github\\.com:([^/]+)\\/([^.]+)/);\n if (sshMatch) {\n return { owner: sshMatch[1], repo: sshMatch[2] };\n }\n\n // Handle HTTPS format: https://github.com/owner/repo.git\n const httpsMatch = url.match(/github\\.com\\/([^/]+)\\/([^.]+)/);\n if (httpsMatch) {\n return { owner: httpsMatch[1], repo: httpsMatch[2] };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\nexport async function getCommitsSinceBase(\n base: string = \"main\"\n): Promise<string[]> {\n try {\n const { stdout } = await execa(\"git\", [\n \"log\",\n `${base}..HEAD`,\n \"--pretty=format:%s\",\n ]);\n return stdout.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\nexport async function getDiffSummary(base: string = \"main\"): Promise<string> {\n try {\n const { stdout } = await execa(\"git\", [\"diff\", `${base}...HEAD`, \"--stat\"]);\n return stdout.trim();\n } catch {\n return \"\";\n }\n}\n\nexport async function getCurrentCommitSha(): Promise<string> {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"HEAD\"]);\n return stdout.trim();\n}\n\nexport async function hasNewCommits(beforeSha: string): Promise<boolean> {\n const currentSha = await getCurrentCommitSha();\n return currentSha !== beforeSha;\n}\n\nexport async function getLastCommitTimestamp(): Promise<string> {\n const { stdout } = await execa(\"git\", [\"log\", \"-1\", \"--format=%cI\"]);\n return stdout.trim();\n}\n\nexport async function listLocalBranches(): Promise<string[]> {\n const { stdout } = await execa(\"git\", [\n \"branch\",\n \"--format=%(refname:short)\",\n ]);\n return stdout.trim().split(\"\\n\").filter(Boolean);\n}\n\nexport async function remoteBranchExists(name: string): Promise<boolean> {\n try {\n await execa(\"git\", [\"ls-remote\", \"--exit-code\", \"--heads\", \"origin\", name]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function fetchAndCheckout(name: string): Promise<void> {\n await execa(\"git\", [\"fetch\", \"origin\", `${name}:${name}`]);\n await execa(\"git\", [\"checkout\", name]);\n}\n"],"mappings":"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","names":["execa","execa","execa"]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
checkGhAuth,
|
|
4
4
|
getCurrentBranch,
|
|
5
5
|
logger
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6CFTGBMW.js";
|
|
7
7
|
|
|
8
8
|
// src/commands/github-remote.ts
|
|
9
9
|
import { execa } from "execa";
|
|
@@ -40,4 +40,4 @@ async function githubRemoteCommand() {
|
|
|
40
40
|
export {
|
|
41
41
|
githubRemoteCommand
|
|
42
42
|
};
|
|
43
|
-
//# sourceMappingURL=chunk-
|
|
43
|
+
//# sourceMappingURL=chunk-ALH7P5G7.js.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
getRepoInfo,
|
|
7
7
|
loadConfig,
|
|
8
8
|
logger
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-6CFTGBMW.js";
|
|
10
10
|
|
|
11
11
|
// src/utils/spinner.ts
|
|
12
12
|
import ora from "ora";
|
|
@@ -280,4 +280,4 @@ export {
|
|
|
280
280
|
sortByPriority,
|
|
281
281
|
setupLabelsCommand
|
|
282
282
|
};
|
|
283
|
-
//# sourceMappingURL=chunk-
|
|
283
|
+
//# sourceMappingURL=chunk-ZJCC7PIU.js.map
|