@ztimson/ai-agents 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ Copyright (c) 2023 Zakary Timson
2
+
3
+ All Rights Reserved.
4
+
5
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
7
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
10
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
11
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ <!-- Header -->
2
+ <div id="top" align="center">
3
+ <br />
4
+
5
+ <!-- Logo -->
6
+ <img src="https://git.zakscode.com/repo-avatars/d2c56ffd0220751c2f4a9f6fc1e8125a9a63aeed452ae4f4ab696c084330faa2" alt="Logo" width="200" height="200">
7
+
8
+ <!-- Title -->
9
+ ### AI Agents
10
+
11
+ <!-- Description -->
12
+ Automated AI-powered agents for automated reviews and code assistance
13
+
14
+ <!-- Repo badges -->
15
+ [![Version](https://img.shields.io/badge/dynamic/json.svg?label=Version&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ai-agents/tags&query=$[0].name)](https://git.zakscode.com/ztimson/ai-agents/tags)
16
+ [![Pull Requests](https://img.shields.io/badge/dynamic/json.svg?label=Pull%20Requests&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ai-agents&query=open_pr_counter)](https://git.zakscode.com/ztimson/ai-agents/pulls)
17
+ [![Issues](https://img.shields.io/badge/dynamic/json.svg?label=Issues&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ai-agents&query=open_issues_count)](https://git.zakscode.com/ztimson/ai-agents/issues)
18
+
19
+ <!-- Links -->
20
+ ---
21
+ <div>
22
+ <a href="https://git.zakscode.com/ztimson/ai-agents/releases" target="_blank">Release Notes</a>
23
+ • <a href="https://git.zakscode.com/ztimson/ai-agents/issues/new?template=.github%2fissue_template%2fbug.md" target="_blank">Report a Bug</a>
24
+ • <a href="https://git.zakscode.com/ztimson/ai-agents/issues/new?template=.github%2fissue_template%2fenhancement.md" target="_blank">Request a Feature</a>
25
+ </div>
26
+
27
+ ---
28
+ </div>
29
+
30
+ ## Table of Contents
31
+ - [AI Agents](#top)
32
+ - [About](#about)
33
+ - [Built With](#built-with)
34
+ - [Setup](#setup)
35
+ - [Production](#production)
36
+ - [License](#license)
37
+
38
+ ## About
39
+
40
+ Automated code agents that uses AI to analyze git diffs and provide inline comments on pull requests. Supports Anthropic, OpenAI, and Ollama models with tool-based reviewing for precise feedback.
41
+
42
+ ### Built With
43
+ [![Docker](https://img.shields.io/badge/Docker-384d54?style=for-the-badge&logo=docker)](https://docker.com/)
44
+ [![JavaScript](https://img.shields.io/badge/JavaScript-000000?style=for-the-badge&logo=javascript)](https://javascript.com/)
45
+ [![Node](https://img.shields.io/badge/Node.js-000000?style=for-the-badge&logo=nodedotjs)](https://nodejs.org/)
46
+
47
+ ## Setup
48
+
49
+ <details>
50
+ <summary>
51
+ <h3 id="production" style="display: inline">
52
+ Production
53
+ </h3>
54
+ </summary>
55
+
56
+ #### Instructions
57
+ 1. Run using npx: `npx @ztimson/ai-agents review`
58
+
59
+ </details>
60
+
61
+ <details>
62
+ <summary>
63
+ <h3 id="development" style="display: inline">
64
+ Development
65
+ </h3>
66
+ </summary>
67
+
68
+ #### Prerequisites
69
+ - [Node.js](https://nodejs.org/en/download)
70
+
71
+ #### Instructions
72
+ 1. Install the dependencies: `npm i`
73
+ 2. Build library: `npm run review`
74
+
75
+ </details>
76
+
77
+ ## License
78
+
79
+ Copyright © 2025 Zakary Timson | All Rights Reserved | Available under MIT Licensing
80
+
81
+ See the [license](./LICENSE) for more information.
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@ztimson/ai-agents",
3
+ "version": "0.0.0",
4
+ "description": "AI agents",
5
+ "keywords": ["ai", "review"],
6
+ "author": "ztimson",
7
+ "license": "ISC",
8
+ "bin": {
9
+ "review": "./src/review.mjs"
10
+ },
11
+ "dependencies": {
12
+ "@ztimson/ai-utils": "^0.2.4",
13
+ "@ztimson/node-utils": "^1.0.7",
14
+ "@ztimson/utils": "^0.28.3",
15
+ "dotenv": "^17.2.3"
16
+ },
17
+ "files": [
18
+ "src/"
19
+ ]
20
+ }
package/src/review.mjs ADDED
@@ -0,0 +1,94 @@
1
+ import {Ai} from '@ztimson/ai-utils';
2
+ import {$} from '@ztimson/node-utils';
3
+ import * as os from 'node:os';
4
+ import * as path from 'node:path';
5
+ import * as fs from 'node:fs';
6
+ import * as dotenv from 'dotenv';
7
+
8
+ dotenv.config({quiet: true, debug: false});
9
+ dotenv.config({path: '.env.local', override: true, quiet: true, debug: false});
10
+
11
+ (async () => {
12
+ const root = process.argv[2] || process.cwd(),
13
+ branch = process.env['GIT_BRANCH'] || await $`cd ${root} && git symbolic-ref refs/remotes/origin/HEAD`,
14
+ git = process.env['GIT_HOST'],
15
+ owner = process.env['GIT_OWNER'],
16
+ repo = process.env['GIT_REPO'],
17
+ auth = process.env['GIT_TOKEN'],
18
+ pr = process.env['PULL_REQUEST'],
19
+ host = process.env['AI_HOST'],
20
+ model = process.env['AI_MODEL'],
21
+ token = process.env['AI_TOKEN'];
22
+
23
+ console.log(`Reviewing: ${root}\n`);
24
+ const comments = [];
25
+ const commit = await $`cd ${root} && git log -1 --pretty=format:%H`;
26
+ const gitDiff = await $`cd ${root} && git diff ${branch}`;
27
+
28
+
29
+ let options = {ollama: {model, host}};
30
+ if(host === 'anthropic') options = {anthropic: {model, token}};
31
+ else if(host === 'openai') options = {openAi: {model, token}};
32
+ const ai = new Ai({
33
+ ...options,
34
+ model: [host, model],
35
+ path: process.env['path'] || os.tmpdir(),
36
+ system: `You are a code reviewer. Analyze the git diff and use the \`recommend\` tool for EACH issue you find. You must call \`recommend\` exactly once for every bug or improvement opportunity. After making all recommendations, provide a brief bullet point summary in markdown.`,
37
+ tools: [{
38
+ name: 'read_file',
39
+ description: 'Read contents of a file',
40
+ args: {
41
+ path: {type: 'string', description: 'Path to file relative to project root'}
42
+ },
43
+ fn: (args) => fs.readFileSync(path.join(root, args.path), 'utf-8')
44
+ }, {
45
+ name: 'get_diff',
46
+ description: 'Check a file for differences using git',
47
+ args: {
48
+ path: {type: 'string', description: 'Path to file relative to project root'}
49
+ },
50
+ fn: async (args) => await $`git diff HEAD^..HEAD -- ${path.join(root, args.path)}`
51
+ }, {
52
+ name: 'recommend',
53
+ description: 'REQUIRED: Call this once for every bug, improvement, or concern identified in the review.',
54
+ args: {
55
+ file: {type: 'string', description: 'File path'},
56
+ line: {type: 'number', description: 'Line number in new file'},
57
+ comment: {type: 'string', description: 'Review comment explaining the issue'}
58
+ },
59
+ fn: (args) => {
60
+ comments.push({
61
+ path: args.file,
62
+ new_position: args.line,
63
+ body: args.comment,
64
+ });
65
+ return 'Comment recorded, continue reviewing';
66
+ }
67
+ }]
68
+ });
69
+
70
+ if(!gitDiff) {
71
+ console.warn('No diff found');
72
+ return process.exit();
73
+ }
74
+
75
+ const messages = await ai.language.ask(gitDiff);
76
+ const summary = messages.pop().content;
77
+ if(git) {
78
+ const res = await fetch(`${git}/api/v1/repos/${owner}/${repo}/pulls/${pr}/reviews`, {
79
+ method: 'POST',
80
+ headers: {
81
+ 'Authorization': `token ${auth}`,
82
+ 'Content-Type': 'application/json'
83
+ },
84
+ body: JSON.stringify({
85
+ body: summary,
86
+ commit_id: commit,
87
+ event: 'COMMENT',
88
+ comments,
89
+ })
90
+ });
91
+ if(!res.ok) throw new Error(`${res.status} ${await res.text()}`);
92
+ }
93
+ console.log(comments.map(c => `${c.path}${c.new_position ? `:${c.new_position}` : ''}\n${c.body}`).join('\n\n') + '\n\n' + summary);
94
+ })();