Fixed ticket refining labels
All checks were successful
Publish Library / Build NPM Project (push) Successful in 5s
Publish Library / Tag Version (push) Successful in 4s

This commit is contained in:
2025-12-30 19:09:38 -05:00
parent 27fad6a3d3
commit c7f8ffb32a
2 changed files with 73 additions and 53 deletions

View File

@@ -8,46 +8,12 @@ labels:
--- ---
# [Module] - [Add/Change/Fix/Refactor/Remove] [Feature/Component] Describe your request:
## Type: [Bug/DevOps/Enhancement/Refactor/Security] What are you trying to do and what's happening?
| | Score | How can it be fixed or improved?
|------------|----------|
| Size | 0-5 |
| Complexity | 0-5 |
| Unknowns | 0-5 |
| **Total** | **0-15** |
## Description Steps to reproduce?
A clear explanation of the issue, feature, or change needed Anything other useful information, logs or screenshots?
## Current Behavior
For bugs: what's happening now
For refactors: what exists today
For enhancements: current state/gap
## Expected Behavior
What should happen instead
## Steps to Reproduce
1. First step
2. Second step
3. Third step
## Additional Context
Logs, screenshots, links, related issues
## Acceptance Criteria
- [ ] Todo requirement
- [X] Completed requirement
## Technical Notes
Implementation details, constraints, dependencies, design decisions

View File

@@ -14,8 +14,6 @@ dotenv.config({path: '.env.local', override: true, quiet: true});
if(p === 'refine' || p.endsWith('refine.mjs')) p = null; if(p === 'refine' || p.endsWith('refine.mjs')) p = null;
if(!/^(\/|[A-Z]:)/m.test(p)) p = path.join(process.cwd(), p); if(!/^(\/|[A-Z]:)/m.test(p)) p = path.join(process.cwd(), p);
if(!p || !fs.existsSync(p)) throw new Error('Please provide a template');
const git = process.env['GIT_HOST'], const git = process.env['GIT_HOST'],
owner = process.env['GIT_OWNER'], owner = process.env['GIT_OWNER'],
repo = process.env['GIT_REPO'], repo = process.env['GIT_REPO'],
@@ -38,9 +36,49 @@ dotenv.config({path: '.env.local', override: true, quiet: true});
return process.exit(); return process.exit();
} }
let readme = '', readmeP = path.join(process.cwd(), 'README.md'); let title = '', type = '', readme = '', readmeP = path.join(process.cwd(), 'README.md');
if(fs.existsSync(readmeP)) readme = fs.readFileSync(readmeP, 'utf-8'); if(fs.existsSync(readmeP)) readme = fs.readFileSync(readmeP, 'utf-8');
const template = fs.readFileSync(p, 'utf-8'); const template = p ? fs.readFileSync(p, 'utf-8') : `## Description
A clear explanation of the request
---
## Current Behavior
what's happening now or the current state/gap
## Expected Behavior
What should happen instead
## Steps to Reproduce
1. First step
2. Second step
3. Third step
## Additional Context
Logs, screenshots, links, related issues
## Acceptance Criteria
- [ ] Todo requirement
- [X] Completed requirement
## Technical Notes
Implementation details, constraints, dependencies, design decisions
| Effort / Weight | Score |
|-----------------|----------|
| Size | 0-5 |
| Complexity | 0-5 |
| Unknowns | 0-5 |
| **Total** | **0-15** |
`;
let options = {ollama: {model, host}}; let options = {ollama: {model, host}};
if(host === 'anthropic') options = {anthropic: {model, token}}; if(host === 'anthropic') options = {anthropic: {model, token}};
@@ -49,18 +87,30 @@ dotenv.config({path: '.env.local', override: true, quiet: true});
...options, ...options,
model: [host, model], model: [host, model],
path: process.env['path'] || os.tmpdir(), path: process.env['path'] || os.tmpdir(),
tools: [{
name: 'title',
description: 'Set the ticket title, must be called EXACTLY ONCE',
args: {value: {type: 'string', description: 'Ticket title, must match format: [Module] - [Verb] [noun]', required: true}},
fn: (args) => title = args.title
}, {
name: 'type',
description: 'Set the ticket type, must be called EXACTLY ONCE',
args: {type: {type: 'string', description: 'Ticket type', enum: ['Bug', 'DevOps', 'Document', 'Enhancement', 'Refactor', 'Security'], required: true}},
fn: (args) => type = args.type
}],
system: `You are a ticket formatter. Transform raw issue descriptions into structured tickets. system: `You are a ticket formatter. Transform raw issue descriptions into structured tickets.
**CRITICAL RULES:** **CRITICAL RULES:**
1. Identify the ticket type (Bug, DevOps, Enhancement, Refactor, Security) 1. Identify the ticket type (Bug, DevOps, Enhancement, Refactor, Security)
2. Output MUST only contain the new ticket information in markdown, no extra fluff 2. Output MUST only contain the new ticket information in markdown, no extra fluff
3. Follow the template structure EXACTLY: 3. Follow the template structure EXACTLY:
- Title format: [Module] - [Verb] [noun] - You must call the \`title\` tool EXACTLY ONCE with the title matching this format: [Module] - [Verb] [noun]
Example: Storage - Fix file uploads Example: Storage - Fix file uploads
- Fill in the identified ticket type - You must call the \`type\` tool EXACTLY ONCE with the identified ticket type
- Write a clear description - Write a clear description
- For bugs: fill Steps to Reproduce with numbered list - For bugs: fill Steps to Reproduce with numbered list
- For enhancements/refactors: REMOVE the Steps to Reproduce section entirely - For enhancements/refactors: REMOVE the Steps to Reproduce section entirely
- For documentation: REMOVE the Current Behavior, Expected Behavior and Steps to Reproduce sections entirely
- Acceptance Criteria: convert requirements into checkboxes (- [ ]) - Acceptance Criteria: convert requirements into checkboxes (- [ ])
- Weight scoring (0-5 each): - Weight scoring (0-5 each):
* Size: Number of modules, layers & files affected by change * Size: Number of modules, layers & files affected by change
@@ -81,18 +131,14 @@ ${template.trim()}
\`\`\` \`\`\`
Output ONLY the formatted ticket, no explanation.` Output ONLY the formatted ticket, no explanation.`
}) });
const messages = await ai.language.ask(`Title: ${issueData.title}\n\nDescription:\n${issueData.body || 'No description provided'}`).catch(() => []); const messages = await ai.language.ask(`Title: ${issueData.title}\n\nDescription:\n${issueData.body || 'No description provided'}`).catch(() => []);
const content = messages?.pop()?.content; const body = messages?.pop()?.content;
if(!content) { if(!body) {
console.log('Invalid response from AI'); console.log('Invalid response from AI');
return process.exit(1); return process.exit(1);
} }
const title = /^# (.+)$/m.exec(content)?.[1] || issueData.title;
const typeMatch = /^## Type:\s*(.+)$/m.exec(content);
const type = typeMatch?.[1]?.split('/')[0]?.trim() || 'Unassigned';
const body = content.replace(/^# .+$/m, '').replace(/^## Type:.+$/m, '').trim();
const updateRes = await fetch(`${git}/api/v1/repos/${owner}/${repo}/issues/${ticket}`, { const updateRes = await fetch(`${git}/api/v1/repos/${owner}/${repo}/issues/${ticket}`, {
method: 'PATCH', method: 'PATCH',
headers: { headers: {
@@ -102,9 +148,17 @@ Output ONLY the formatted ticket, no explanation.`
body: JSON.stringify({ body: JSON.stringify({
title, title,
body, body,
labels: type?.length ? [`Kind/${type[0].toUpperCase() + type.slice(1).toLowerCase()}`] : []
}) })
}); });
if(!updateRes.ok) throw new Error(`${updateRes.status} ${await updateRes.text()}`); if(!updateRes.ok) throw new Error(`${updateRes.status} ${await updateRes.text()}`);
if(type) fetch(`${git}/api/v1/repos/${owner}/${repo}/issues/${ticket}/labels`, {
method: 'POST',
headers: {
'Authorization': `token ${auth}`,
'Content-Type': 'application/json'
},
body: `["Kind/${type[0].toUpperCase() + type.slice(1).toLowerCase()}"]`
})
console.log(body); console.log(body);
})(); })();