@ztimson/ai-agents 0.1.2 → 0.1.4
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 +5 -2
- package/package.json +2 -1
- package/src/release.mjs +90 -0
- package/src/review.mjs +1 -1
package/README.md
CHANGED
|
@@ -37,9 +37,12 @@ AI-powered Gitea agents for automating reviews and administration
|
|
|
37
37
|
|
|
38
38
|
## About
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
AI-powered Gitea agents for automating administration of code repos:
|
|
41
|
+
- Code Review
|
|
42
|
+
- Release Notes
|
|
43
|
+
- Ticket Refinement
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
Only supports Gitea, copy the relevant `.github/workflows/______.yml` action to start using it
|
|
43
46
|
|
|
44
47
|
### Built With
|
|
45
48
|
[](https://docker.com/)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ztimson/ai-agents",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "AI agents",
|
|
5
5
|
"keywords": ["ai", "review"],
|
|
6
6
|
"author": "ztimson",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"type": "module",
|
|
9
9
|
"bin": {
|
|
10
10
|
"refine": "./src/refine.mjs",
|
|
11
|
+
"release": "./src/release.mjs",
|
|
11
12
|
"review": "./src/review.mjs"
|
|
12
13
|
},
|
|
13
14
|
"dependencies": {
|
package/src/release.mjs
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {Ai} from '@ztimson/ai';
|
|
3
|
+
import * as dotenv from 'dotenv';
|
|
4
|
+
import {$} from '@ztimson/node-utils';
|
|
5
|
+
|
|
6
|
+
dotenv.config({quiet: true, debug: false});
|
|
7
|
+
dotenv.config({path: '.env.local', override: true, quiet: true, debug: false});
|
|
8
|
+
|
|
9
|
+
(async () => {
|
|
10
|
+
const git = process.env['GIT_HOST'],
|
|
11
|
+
owner = process.env['GIT_OWNER'],
|
|
12
|
+
repo = process.env['GIT_REPO'],
|
|
13
|
+
auth = process.env['GIT_TOKEN'],
|
|
14
|
+
milestone = process.env['MILESTONE'],
|
|
15
|
+
host = process.env['AI_HOST'] || 'ollama',
|
|
16
|
+
model = process.env['AI_MODEL'] || 'llama3',
|
|
17
|
+
token = process.env['AI_TOKEN'];
|
|
18
|
+
|
|
19
|
+
// Get milestone info
|
|
20
|
+
const milestoneData = await fetch(`${git}/api/v1/repos/${owner}/${repo}/milestones/${milestone}`, {
|
|
21
|
+
headers: {'Authorization': `token ${auth}`}
|
|
22
|
+
}).then(resp => resp.ok ? resp.json() : {});
|
|
23
|
+
|
|
24
|
+
// Get closed issues
|
|
25
|
+
const issues = await fetch(`${git}/api/v1/repos/${owner}/${repo}/issues?state=closed&milestone=${milestone}`, {
|
|
26
|
+
headers: {'Authorization': `token ${auth}`}
|
|
27
|
+
}).then(resp => resp.ok ? resp.json() : []);
|
|
28
|
+
|
|
29
|
+
// Get closed PRs
|
|
30
|
+
const prs = await fetch(`${git}/api/v1/repos/${owner}/${repo}/pulls?state=closed&milestone=${milestone}`, {
|
|
31
|
+
headers: {'Authorization': `token ${auth}`}
|
|
32
|
+
}).then(resp => resp.ok ? resp.json() : []);
|
|
33
|
+
|
|
34
|
+
// Get latest tag
|
|
35
|
+
const latestTag = await $`git describe --tags --abbrev=0`.text();
|
|
36
|
+
if(!latestTag) {
|
|
37
|
+
console.error('At least one Git tag is required');
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Build context
|
|
42
|
+
let context = `Milestone: ${milestoneData.title}
|
|
43
|
+
Description:
|
|
44
|
+
\`\`\`md
|
|
45
|
+
${milestoneData.description || ''}
|
|
46
|
+
\`\`\`
|
|
47
|
+
|
|
48
|
+
PRs:
|
|
49
|
+
${prs.map(pr => `- ${pr.title}\n${pr.body || ''}`).join('\n\n')}
|
|
50
|
+
|
|
51
|
+
Issues:
|
|
52
|
+
${issues.filter(i => !i.pull_request).map(i => `- ${i.title}\n${i.body || ''}`).join('\n\n')}`;
|
|
53
|
+
|
|
54
|
+
// Generate release notes
|
|
55
|
+
let options = {ollama: {model, host}};
|
|
56
|
+
if(host === 'anthropic') options = {anthropic: {model, token}};
|
|
57
|
+
else if(host === 'openai') options = {openAi: {model, token}};
|
|
58
|
+
|
|
59
|
+
const ai = new Ai({
|
|
60
|
+
...options,
|
|
61
|
+
model: [host, model],
|
|
62
|
+
system: `You are a release notes writer. Format the provided milestone info, PRs, and issues into clean, organized release notes. Use markdown with sections like "Features", "Bug Fixes", "Breaking Changes", etc. Be concise but informative. Include issue/PR numbers in format #123.`
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const body = (await ai.chat(context)).pop()?.content;
|
|
66
|
+
if(!body) {
|
|
67
|
+
console.error('No release notes were generated');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Create release
|
|
72
|
+
const name = latestTag.trim();
|
|
73
|
+
await fetch(`${git}/api/v1/repos/${owner}/${repo}/releases`, {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
headers: {
|
|
76
|
+
'Authorization': `token ${auth}`,
|
|
77
|
+
'Content-Type': 'application/json'
|
|
78
|
+
},
|
|
79
|
+
body: JSON.stringify({
|
|
80
|
+
name,
|
|
81
|
+
tag_name: name,
|
|
82
|
+
body
|
|
83
|
+
})
|
|
84
|
+
}).then(resp => { if(!resp.ok) throw new Error(resp.status + ' ' + resp.statusText) });
|
|
85
|
+
|
|
86
|
+
console.log(`Title: ${name}\nDescription:\n${body}`);
|
|
87
|
+
})().catch(err => {
|
|
88
|
+
console.error(`Error: ${err.message || err.toString()}`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
});
|
package/src/review.mjs
CHANGED
|
@@ -25,7 +25,7 @@ dotenv.config({path: '.env.local', override: true, quiet: true, debug: false});
|
|
|
25
25
|
model = process.env['AI_MODEL'],
|
|
26
26
|
token = process.env['AI_TOKEN'];
|
|
27
27
|
|
|
28
|
-
console.log(`Reviewing: ${root}
|
|
28
|
+
console.log(`Reviewing: ${root}`);
|
|
29
29
|
const info = await fetch(`${git}/api/v1/repos/${owner}/${repo}/pulls/${pr}`)
|
|
30
30
|
.then(async resp => {
|
|
31
31
|
if(resp.ok) return resp.json();
|