gaunt-sloth-assistant 0.1.5 → 0.3.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/{.gsloth.preamble.review.md → .gsloth.guidelines.md} +0 -8
- package/.gsloth.review.md +7 -0
- package/.prettierrc.json +9 -0
- package/README.md +177 -158
- package/ROADMAP.md +1 -1
- package/dist/commands/askCommand.d.ts +6 -0
- package/dist/commands/askCommand.js +27 -0
- package/dist/commands/askCommand.js.map +1 -0
- package/dist/commands/initCommand.d.ts +6 -0
- package/dist/commands/initCommand.js +16 -0
- package/dist/commands/initCommand.js.map +1 -0
- package/dist/commands/reviewCommand.d.ts +3 -0
- package/dist/commands/reviewCommand.js +142 -0
- package/dist/commands/reviewCommand.js.map +1 -0
- package/dist/config.d.ts +84 -0
- package/dist/config.js +180 -0
- package/dist/config.js.map +1 -0
- package/dist/configs/anthropic.d.ts +4 -0
- package/{src → dist}/configs/anthropic.js +45 -48
- package/dist/configs/anthropic.js.map +1 -0
- package/dist/configs/fake.d.ts +3 -0
- package/{src → dist}/configs/fake.js +11 -14
- package/dist/configs/fake.js.map +1 -0
- package/dist/configs/groq.d.ts +4 -0
- package/{src → dist}/configs/groq.js +10 -13
- package/dist/configs/groq.js.map +1 -0
- package/dist/configs/types.d.ts +14 -0
- package/dist/configs/types.js +2 -0
- package/dist/configs/types.js.map +1 -0
- package/dist/configs/vertexai.d.ts +4 -0
- package/{src → dist}/configs/vertexai.js +44 -47
- package/dist/configs/vertexai.js.map +1 -0
- package/dist/consoleUtils.d.ts +6 -0
- package/{src → dist}/consoleUtils.js +10 -15
- package/dist/consoleUtils.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/llmUtils.d.ts +4 -0
- package/dist/llmUtils.js +39 -0
- package/dist/llmUtils.js.map +1 -0
- package/dist/modules/questionAnsweringModule.d.ts +7 -0
- package/dist/modules/questionAnsweringModule.js +33 -0
- package/dist/modules/questionAnsweringModule.js.map +1 -0
- package/dist/modules/reviewModule.d.ts +1 -0
- package/dist/modules/reviewModule.js +29 -0
- package/dist/modules/reviewModule.js.map +1 -0
- package/dist/modules/types.d.ts +18 -0
- package/dist/modules/types.js +2 -0
- package/dist/modules/types.js.map +1 -0
- package/dist/prompt.d.ts +8 -0
- package/dist/prompt.js +45 -0
- package/dist/prompt.js.map +1 -0
- package/dist/providers/file.d.ts +8 -0
- package/dist/providers/file.js +20 -0
- package/dist/providers/file.js.map +1 -0
- package/dist/providers/ghPrDiffProvider.d.ts +8 -0
- package/dist/providers/ghPrDiffProvider.js +16 -0
- package/dist/providers/ghPrDiffProvider.js.map +1 -0
- package/dist/providers/jiraIssueLegacyAccessTokenProvider.d.ts +8 -0
- package/dist/providers/jiraIssueLegacyAccessTokenProvider.js +62 -0
- package/dist/providers/jiraIssueLegacyAccessTokenProvider.js.map +1 -0
- package/dist/providers/jiraIssueLegacyProvider.d.ts +8 -0
- package/dist/providers/jiraIssueLegacyProvider.js +74 -0
- package/dist/providers/jiraIssueLegacyProvider.js.map +1 -0
- package/dist/providers/jiraIssueProvider.d.ts +11 -0
- package/dist/providers/jiraIssueProvider.js +96 -0
- package/dist/providers/jiraIssueProvider.js.map +1 -0
- package/dist/providers/text.d.ts +8 -0
- package/dist/providers/text.js +10 -0
- package/dist/providers/text.js.map +1 -0
- package/dist/providers/types.d.ts +21 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/systemUtils.d.ts +32 -0
- package/dist/systemUtils.js +70 -0
- package/dist/systemUtils.js.map +1 -0
- package/dist/utils.d.ts +49 -0
- package/dist/utils.js +192 -0
- package/dist/utils.js.map +1 -0
- package/docs/CONFIGURATION.md +99 -10
- package/docs/RELEASE-HOWTO.md +7 -1
- package/eslint.config.js +99 -21
- package/gth-ASK-2025-05-16T14-11-39.md +3 -0
- package/gth-ASK-2025-05-16T14-18-27.md +3 -0
- package/gth-ASK-2025-05-16T14-18-56.md +1 -0
- package/gth-ASK-2025-05-16T14-41-20.md +3 -0
- package/gth-ASK-2025-05-16T14-43-31.md +51 -0
- package/gth-ASK-2025-05-16T16-05-52.md +62 -0
- package/gth-DIFF-review-2025-05-16T16-07-53.md +56 -0
- package/gth-DIFF-review-2025-05-16T16-18-55.md +292 -0
- package/index.js +10 -27
- package/package.json +26 -15
- package/src/commands/askCommand.ts +35 -0
- package/src/commands/initCommand.ts +19 -0
- package/src/commands/reviewCommand.ts +223 -0
- package/src/config.ts +269 -0
- package/src/configs/anthropic.ts +57 -0
- package/src/configs/fake.ts +15 -0
- package/src/configs/groq.ts +54 -0
- package/src/configs/vertexai.ts +53 -0
- package/src/consoleUtils.ts +33 -0
- package/src/index.ts +30 -0
- package/src/llmUtils.ts +54 -0
- package/src/modules/questionAnsweringModule.ts +44 -0
- package/src/modules/reviewModule.ts +31 -0
- package/src/modules/types.ts +23 -0
- package/src/prompt.ts +54 -0
- package/src/providers/file.ts +24 -0
- package/src/providers/ghPrDiffProvider.ts +20 -0
- package/src/providers/jiraIssueLegacyProvider.ts +103 -0
- package/src/providers/jiraIssueProvider.ts +133 -0
- package/src/providers/text.ts +14 -0
- package/src/providers/types.ts +24 -0
- package/src/systemUtils.ts +90 -0
- package/src/utils.ts +232 -0
- package/tsconfig.json +24 -0
- package/vitest.config.ts +13 -0
- package/.eslint.config.mjs +0 -72
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/ci.yml +0 -33
- package/spec/.gsloth.config.js +0 -22
- package/spec/.gsloth.config.json +0 -25
- package/spec/askCommand.spec.js +0 -92
- package/spec/config.spec.js +0 -421
- package/spec/initCommand.spec.js +0 -55
- package/spec/predefinedConfigs.spec.js +0 -100
- package/spec/questionAnsweringModule.spec.js +0 -137
- package/spec/reviewCommand.spec.js +0 -222
- package/spec/reviewModule.spec.js +0 -28
- package/spec/support/jasmine.mjs +0 -14
- package/src/commands/askCommand.js +0 -27
- package/src/commands/initCommand.js +0 -17
- package/src/commands/reviewCommand.js +0 -154
- package/src/config.js +0 -177
- package/src/modules/questionAnsweringModule.js +0 -82
- package/src/modules/reviewModule.js +0 -70
- package/src/prompt.js +0 -34
- package/src/providers/file.js +0 -19
- package/src/providers/ghPrDiffProvider.js +0 -11
- package/src/providers/jiraIssueLegacyAccessTokenProvider.js +0 -84
- package/src/providers/text.js +0 -6
- package/src/systemUtils.js +0 -32
- package/src/utils.js +0 -173
- /package/{.gsloth.preamble.internal.md → .gsloth.backstory.md} +0 -0
@@ -115,11 +115,3 @@ Make sure that API keys are accidentally not included into diff.
|
|
115
115
|
- Resource usage
|
116
116
|
|
117
117
|
---
|
118
|
-
|
119
|
-
Provide specific feedback on any areas of concern or suggestions for improvement. Please categorize your feedback (e.g., "Bug," "Suggestion," "Nitpick").
|
120
|
-
|
121
|
-
Important! In the end conclude if you would recommend to approve this PR or not. Use ✅⚠️❌ symbols to highlight your feedback appropriately.
|
122
|
-
|
123
|
-
Thank you for your thorough review!
|
124
|
-
|
125
|
-
Important! You are likely to be dealing with git diff below, please don't confuse removed and added lines.
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Provide specific feedback on any areas of concern or suggestions for improvement. Please categorize your feedback (e.g., "Bug," "Suggestion," "Nitpick").
|
2
|
+
|
3
|
+
Important! In the end conclude if you would recommend to approve this PR or not. Use ✅⚠️❌ symbols to highlight your feedback appropriately.
|
4
|
+
|
5
|
+
Thank you for your thorough review!
|
6
|
+
|
7
|
+
Important! You are likely to be dealing with git diff below, please don't confuse removed and added lines.
|
package/.prettierrc.json
ADDED
package/README.md
CHANGED
@@ -1,158 +1,177 @@
|
|
1
|
-
# Gaunt Sloth Assistant
|
2
|
-
[](https://github.com/andruhon/gaunt-sloth-assistant/actions/workflows/ci.yml)
|
3
|
-
|
4
|
-
Gaunt Sloth Assistant is a Simplistic **command line AI assistant**
|
5
|
-
for software developers,
|
6
|
-
who wish to reduce cognitive load and time spending on **code reviews** (and pull request diff reviews).
|
7
|
-
|
8
|
-
Based on [Langchain.js](https://github.com/langchain-ai/langchainjs)
|
9
|
-
|
10
|
-
## What GSloth does:
|
11
|
-
- Reviews code;
|
12
|
-
- Suggests bug fixes;
|
13
|
-
- Explains provided code
|
14
|
-
- Reviews Diffs provided with pipe (|);
|
15
|
-
- You can ask GSloth to review your own code before committing.
|
16
|
-
- Reviews Pull Requests (PRs);
|
17
|
-
- Fetches descriptions (requirements) from Jira;
|
18
|
-
- Answers questions about provided code;
|
19
|
-
- Writes code;
|
20
|
-
- Saves all responses to the project directory;
|
21
|
-
- Anything else you need, when combined with other command line tools.
|
22
|
-
|
23
|
-
### To make GSloth work, you need an **API key** from some AI provider, such as:
|
24
|
-
- Google Vertex AI;
|
25
|
-
- Anthropic;
|
26
|
-
- Groq.
|
27
|
-
|
28
|
-
## Primary Functions:
|
29
|
-
|
30
|
-
### Review PR (Pull Request)
|
31
|
-
To review PR by PR number:
|
32
|
-
|
33
|
-
First make sure the official [GitHub cli (gh)](https://cli.github.com/) is installed
|
34
|
-
and authenticated to have access to your project.
|
35
|
-
|
36
|
-
Open terminal (command line) in your project directory.
|
37
|
-
|
38
|
-
Type command: `gsloth pr [desired pull request number]`, for example:
|
39
|
-
|
40
|
-
```shell
|
41
|
-
gsloth pr 42
|
42
|
-
```
|
43
|
-
|
44
|
-
Review providing markdown file with requirements and notes.
|
45
|
-
```shell
|
46
|
-
gsloth pr 42 -f PROJ-1234.md
|
47
|
-
```
|
48
|
-
|
49
|
-
### JIRA Integration
|
50
|
-
|
51
|
-
When JIRA integration is configured, the JIRA issue text can be included alongside the diff for review.
|
52
|
-
The project review preamble can be modified to reject a pull request immediately
|
53
|
-
if it appears to implement something different from what was requested in the requirements.
|
54
|
-
|
55
|
-
The command syntax is generally `gsloth pr <prId> [requirementsId]`,
|
56
|
-
for example, the snippet below does review of PR 42 and
|
57
|
-
supplies description of JIRA issue with number PP-4242:
|
58
|
-
|
59
|
-
```shell
|
60
|
-
gsloth pr 42 PP-4242
|
61
|
-
```
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
```
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
###
|
113
|
-
```shell
|
114
|
-
|
115
|
-
```
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
gsloth
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
1
|
+
# Gaunt Sloth Assistant
|
2
|
+
[](https://github.com/andruhon/gaunt-sloth-assistant/actions/workflows/ci.yml)
|
3
|
+
|
4
|
+
Gaunt Sloth Assistant is a Simplistic **command line AI assistant**
|
5
|
+
for software developers,
|
6
|
+
who wish to reduce cognitive load and time spending on **code reviews** (and pull request diff reviews).
|
7
|
+
|
8
|
+
Based on [Langchain.js](https://github.com/langchain-ai/langchainjs)
|
9
|
+
|
10
|
+
## What GSloth does:
|
11
|
+
- Reviews code;
|
12
|
+
- Suggests bug fixes;
|
13
|
+
- Explains provided code
|
14
|
+
- Reviews Diffs provided with pipe (|);
|
15
|
+
- You can ask GSloth to review your own code before committing.
|
16
|
+
- Reviews Pull Requests (PRs);
|
17
|
+
- Fetches descriptions (requirements) from Jira;
|
18
|
+
- Answers questions about provided code;
|
19
|
+
- Writes code;
|
20
|
+
- Saves all responses to the project directory;
|
21
|
+
- Anything else you need, when combined with other command line tools.
|
22
|
+
|
23
|
+
### To make GSloth work, you need an **API key** from some AI provider, such as:
|
24
|
+
- Google Vertex AI;
|
25
|
+
- Anthropic;
|
26
|
+
- Groq.
|
27
|
+
|
28
|
+
## Primary Functions:
|
29
|
+
|
30
|
+
### Review PR (Pull Request)
|
31
|
+
To review PR by PR number:
|
32
|
+
|
33
|
+
First make sure the official [GitHub cli (gh)](https://cli.github.com/) is installed
|
34
|
+
and authenticated to have access to your project.
|
35
|
+
|
36
|
+
Open terminal (command line) in your project directory.
|
37
|
+
|
38
|
+
Type command: `gsloth pr [desired pull request number]`, for example:
|
39
|
+
|
40
|
+
```shell
|
41
|
+
gsloth pr 42
|
42
|
+
```
|
43
|
+
|
44
|
+
Review providing markdown file with requirements and notes.
|
45
|
+
```shell
|
46
|
+
gsloth pr 42 -f PROJ-1234.md
|
47
|
+
```
|
48
|
+
|
49
|
+
### JIRA Integration
|
50
|
+
|
51
|
+
When JIRA integration is configured, the JIRA issue text can be included alongside the diff for review.
|
52
|
+
The project review preamble can be modified to reject a pull request immediately
|
53
|
+
if it appears to implement something different from what was requested in the requirements.
|
54
|
+
|
55
|
+
The command syntax is generally `gsloth pr <prId> [requirementsId]`,
|
56
|
+
for example, the snippet below does review of PR 42 and
|
57
|
+
supplies description of JIRA issue with number PP-4242:
|
58
|
+
|
59
|
+
```shell
|
60
|
+
gsloth pr 42 PP-4242
|
61
|
+
```
|
62
|
+
|
63
|
+
Gaunt Sloth supports two methods to integrate with JIRA scoped tokens and unscoped tokens:
|
64
|
+
|
65
|
+
#### Modern Jira REST API (Scoped Token)
|
66
|
+
|
67
|
+
This method uses the Atlassian REST API v3 with a Personal Access Token (PAT). It requires your Atlassian Cloud ID.
|
68
|
+
|
69
|
+
**Prerequisites:**
|
70
|
+
|
71
|
+
1. **Cloud ID**: You can find your Cloud ID by visiting `https://yourcompany.atlassian.net/_edge/tenant_info` while authenticated.
|
72
|
+
|
73
|
+
2. **Personal Access Token (PAT)**: Create a PAT with the appropriate permissions from `Atlassian Account Settings -> Security -> Create and manage API tokens -> [Create API token with scopes]`.
|
74
|
+
- For issue access, the recommended permission is `read:jira-work` (classic)
|
75
|
+
|
76
|
+
Example configuration:
|
77
|
+
|
78
|
+
```json
|
79
|
+
{
|
80
|
+
"llm": {"type": "vertexai", "model": "gemini-2.5-pro-preview-05-06"},
|
81
|
+
"requirementsProvider": "jira",
|
82
|
+
"requirementsProviderConfig": {
|
83
|
+
"jira": {
|
84
|
+
"username": "username@yourcompany.com",
|
85
|
+
"token": "YOUR_JIRA_PAT_TOKEN",
|
86
|
+
"cloudId": "YOUR_ATLASSIAN_CLOUD_ID"
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
```
|
91
|
+
|
92
|
+
For better security, you can set these values using environment variables:
|
93
|
+
- `JIRA_USERNAME`: Your JIRA username (e.g., `user@yourcompany.com`).
|
94
|
+
- `JIRA_API_PAT_TOKEN`: Your JIRA Personal Access Token with scopes.
|
95
|
+
- `JIRA_CLOUD_ID`: Your Atlassian Cloud ID.
|
96
|
+
|
97
|
+
For more detailed information, see [CONFIGURATION.md](./docs/CONFIGURATION.md).
|
98
|
+
|
99
|
+
For setup with legacy Unscoped tokens please refer to [CONFIGURATION.md](./docs/CONFIGURATION.md).
|
100
|
+
|
101
|
+
### Review any Diff
|
102
|
+
```shell
|
103
|
+
git --no-pager diff origin/master...yourgitcommithash | gsloth review
|
104
|
+
```
|
105
|
+
(helpful to review a subset of PR)
|
106
|
+
|
107
|
+
Review current local changes:
|
108
|
+
```shell
|
109
|
+
git --no-pager diff | gsloth review
|
110
|
+
```
|
111
|
+
|
112
|
+
### Question Answering
|
113
|
+
```shell
|
114
|
+
gsloth ask "which types of primitives are available in JavaScript?"
|
115
|
+
```
|
116
|
+
|
117
|
+
```shell
|
118
|
+
gsloth ask "Please have a look at this file" -f index.js
|
119
|
+
```
|
120
|
+
|
121
|
+
Multiple files may be provided as well
|
122
|
+
|
123
|
+
```shell
|
124
|
+
gsloth ask "Please have a look at these files" -f index.js test.js
|
125
|
+
```
|
126
|
+
|
127
|
+
## Installation
|
128
|
+
|
129
|
+
Tested with Node 22 LTS.
|
130
|
+
|
131
|
+
### NPM
|
132
|
+
```shell
|
133
|
+
npm install gaunt-sloth-assistant -g
|
134
|
+
```
|
135
|
+
|
136
|
+
## Configuration
|
137
|
+
|
138
|
+
> Gaunt Sloth currently only functions from the directory which has a configuration file (`.gsloth.config.js`, `.gsloth.config.json`, or `.gsloth.config.mjs`) and `.gsloth.guidelines.md`.
|
139
|
+
> Global configuration to invoke gsloth anywhere is in [ROADMAP](ROADMAP.md).
|
140
|
+
|
141
|
+
Configuration can be created with `gsloth init [vendor]` command.
|
142
|
+
Currently, vertexai, anthropic and groq can be configured with `gsloth init [vendor]`.
|
143
|
+
|
144
|
+
More detailed information on configuration can be found in [CONFIGURATION.md](./docs/CONFIGURATION.md)
|
145
|
+
|
146
|
+
### Google Vertex AI
|
147
|
+
```shell
|
148
|
+
cd ./your-project
|
149
|
+
gsloth init vertexai
|
150
|
+
gcloud auth login
|
151
|
+
gcloud auth application-default login
|
152
|
+
```
|
153
|
+
|
154
|
+
### Anthropic
|
155
|
+
|
156
|
+
```shell
|
157
|
+
cd ./your-project
|
158
|
+
gsloth init anthropic
|
159
|
+
```
|
160
|
+
|
161
|
+
Make sure you either define `ANTHROPIC_API_KEY` environment variable or edit your configuration file and set up your key.
|
162
|
+
|
163
|
+
### Groq
|
164
|
+
```shell
|
165
|
+
cd ./your-project
|
166
|
+
gsloth init groq
|
167
|
+
```
|
168
|
+
Make sure you either define `GROQ_API_KEY` environment variable or edit your configuration file and set up your key.
|
169
|
+
|
170
|
+
### Other AI providers
|
171
|
+
Any other AI provider supported by Langchain.js can be configured with js [Config](./docs/CONFIGURATION.md).
|
172
|
+
|
173
|
+
## Building from repo
|
174
|
+
See [DEVELOPMENT.md](./docs/DEVELOPMENT.md)
|
175
|
+
|
176
|
+
## License
|
177
|
+
License is [MIT](https://opensource.org/license/mit). See [LICENSE](LICENSE)
|
package/ROADMAP.md
CHANGED
@@ -17,7 +17,7 @@ Doing the following below and making it work stably should be sufficient to call
|
|
17
17
|
-[ ] Local LLm
|
18
18
|
- [ ] Allow global configuration
|
19
19
|
- [ ] Streamline and stabilize configuration
|
20
|
-
- [
|
20
|
+
- [x] Add JIRA legacy token integration plugin
|
21
21
|
- [ ] Teach assistant to identify important files and include their contents into prompt
|
22
22
|
The idea is to ask smaller model like flash to find important files from diff then pick them up and include into prompt.
|
23
23
|
- [ ] Teach assistant to access provided public web links
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { readBackstory, readGuidelines } from '#src/prompt.js';
|
2
|
+
import { readMultipleFilesFromCurrentDir } from '#src/utils.js';
|
3
|
+
import { initConfig, slothContext } from '#src/config.js';
|
4
|
+
/**
|
5
|
+
* Adds the ask command to the program
|
6
|
+
* @param program - The commander program
|
7
|
+
*/
|
8
|
+
export function askCommand(program) {
|
9
|
+
program
|
10
|
+
.command('ask')
|
11
|
+
.description('Ask a question')
|
12
|
+
.argument('<message>', 'A message')
|
13
|
+
.option('-f, --file [files...]', 'Input files. Content of these files will be added BEFORE the message')
|
14
|
+
// TODO add option consuming extra message as argument
|
15
|
+
.action(async (message, options) => {
|
16
|
+
const preamble = [readBackstory(), readGuidelines(slothContext.config.projectGuidelines)];
|
17
|
+
const content = [message];
|
18
|
+
if (options.file) {
|
19
|
+
content.push(readMultipleFilesFromCurrentDir(options.file));
|
20
|
+
}
|
21
|
+
await initConfig();
|
22
|
+
const { askQuestion } = await import('#src/modules/questionAnsweringModule.js');
|
23
|
+
// TODO make the prefix configurable
|
24
|
+
await askQuestion('gth-ASK', preamble.join('\n'), content.join('\n'));
|
25
|
+
});
|
26
|
+
}
|
27
|
+
//# sourceMappingURL=askCommand.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"askCommand.js","sourceRoot":"","sources":["../../src/commands/askCommand.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,+BAA+B,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM1D;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,gBAAgB,CAAC;SAC7B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;SAClC,MAAM,CACL,uBAAuB,EACvB,sEAAsE,CACvE;QACD,sDAAsD;SACrD,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,OAA0B,EAAE,EAAE;QAC5D,MAAM,QAAQ,GAAG,CAAC,aAAa,EAAE,EAAE,cAAc,CAAC,YAAY,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC1F,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;QAC1B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,UAAU,EAAE,CAAC;QACnB,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,yCAAyC,CAAC,CAAC;QAChF,oCAAoC;QACpC,MAAM,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACP,CAAC"}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { availableDefaultConfigs, createProjectConfig } from '#src/config.js';
|
2
|
+
import { Argument } from 'commander';
|
3
|
+
/**
|
4
|
+
* Adds the init command to the program
|
5
|
+
* @param program - The commander program
|
6
|
+
*/
|
7
|
+
export function initCommand(program) {
|
8
|
+
program
|
9
|
+
.command('init')
|
10
|
+
.description('Initialize the Gaunt Sloth Assistant in your project. This will write necessary config files.')
|
11
|
+
.addArgument(new Argument('<type>', 'Config type').choices(availableDefaultConfigs))
|
12
|
+
.action(async (config) => {
|
13
|
+
await createProjectConfig(config);
|
14
|
+
});
|
15
|
+
}
|
16
|
+
//# sourceMappingURL=initCommand.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"initCommand.js","sourceRoot":"","sources":["../../src/commands/initCommand.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAW,MAAM,WAAW,CAAC;AAE9C;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CACV,+FAA+F,CAChG;SACA,WAAW,CAAC,IAAI,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;SACnF,MAAM,CAAC,KAAK,EAAE,MAAkB,EAAE,EAAE;QACnC,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
@@ -0,0 +1,142 @@
|
|
1
|
+
import { Option } from 'commander';
|
2
|
+
import { slothContext } from '#src/config.js';
|
3
|
+
import { readBackstory, readGuidelines, readReviewInstructions } from '#src/prompt.js';
|
4
|
+
import { readMultipleFilesFromCurrentDir } from '#src/utils.js';
|
5
|
+
import { displayError } from '#src/consoleUtils.js';
|
6
|
+
import { getStringFromStdin } from '#src/systemUtils.js';
|
7
|
+
/**
|
8
|
+
* Requirements providers. Expected to be in `.providers/` dir
|
9
|
+
*/
|
10
|
+
const REQUIREMENTS_PROVIDERS = {
|
11
|
+
'jira-legacy': 'jiraIssueLegacyProvider.js',
|
12
|
+
jira: 'jiraIssueProvider.js',
|
13
|
+
text: 'text.js',
|
14
|
+
file: 'file.js',
|
15
|
+
};
|
16
|
+
/**
|
17
|
+
* Content providers. Expected to be in `.providers/` dir
|
18
|
+
*/
|
19
|
+
const CONTENT_PROVIDERS = {
|
20
|
+
gh: 'ghPrDiffProvider.js',
|
21
|
+
text: 'text.js',
|
22
|
+
file: 'file.js',
|
23
|
+
};
|
24
|
+
export function reviewCommand(program, context) {
|
25
|
+
program
|
26
|
+
.command('review')
|
27
|
+
.description('Review provided diff or other content')
|
28
|
+
.argument('[contentId]', 'Optional content ID argument to retrieve content with content provider')
|
29
|
+
.alias('r')
|
30
|
+
// TODO add provider to get results of git --no-pager diff
|
31
|
+
.option('-f, --file [files...]', 'Input files. Content of these files will be added BEFORE the diff, but after requirements')
|
32
|
+
// TODO figure out what to do with this (we probably want to merge it with requirementsId)?
|
33
|
+
.option('-r, --requirements <requirements>', 'Requirements for this review.')
|
34
|
+
.addOption(new Option('-p, --requirements-provider <requirementsProvider>', 'Requirements provider for this review.').choices(Object.keys(REQUIREMENTS_PROVIDERS)))
|
35
|
+
.addOption(new Option('--content-provider <contentProvider>', 'Content provider').choices(Object.keys(CONTENT_PROVIDERS)))
|
36
|
+
.option('-m, --message <message>', 'Extra message to provide just before the content')
|
37
|
+
.action(async (contentId, options) => {
|
38
|
+
const { initConfig } = await import('#src/config.js');
|
39
|
+
await initConfig();
|
40
|
+
const systemMessage = [
|
41
|
+
readBackstory(),
|
42
|
+
readGuidelines(slothContext.config.projectGuidelines),
|
43
|
+
readReviewInstructions(slothContext.config.projectReviewInstructions),
|
44
|
+
];
|
45
|
+
const content = [];
|
46
|
+
const requirementsId = options.requirements;
|
47
|
+
const requirementsProvider = options.requirementsProvider ??
|
48
|
+
context.config?.review?.requirementsProvider ??
|
49
|
+
context.config?.requirementsProvider;
|
50
|
+
const contentProvider = options.contentProvider ??
|
51
|
+
context.config?.review?.contentProvider ??
|
52
|
+
context.config?.contentProvider;
|
53
|
+
// TODO consider calling these in parallel
|
54
|
+
const requirements = await getRequirementsFromProvider(requirementsProvider, requirementsId);
|
55
|
+
if (requirements) {
|
56
|
+
content.push(requirements);
|
57
|
+
}
|
58
|
+
const providedContent = await getContentFromProvider(contentProvider, contentId);
|
59
|
+
if (providedContent) {
|
60
|
+
content.push(providedContent);
|
61
|
+
}
|
62
|
+
if (options.file) {
|
63
|
+
content.push(readMultipleFilesFromCurrentDir(options.file));
|
64
|
+
}
|
65
|
+
let stringFromStdin = getStringFromStdin();
|
66
|
+
if (stringFromStdin) {
|
67
|
+
content.push(stringFromStdin);
|
68
|
+
}
|
69
|
+
if (options.message) {
|
70
|
+
content.push(options.message);
|
71
|
+
}
|
72
|
+
const { review } = await import('#src/modules/reviewModule.js');
|
73
|
+
// TODO make the prefix configurable
|
74
|
+
await review('gth-DIFF-review', systemMessage.join('\n'), content.join('\n'));
|
75
|
+
});
|
76
|
+
program
|
77
|
+
.command('pr')
|
78
|
+
.description('Review provided Pull Request in current directory. ' +
|
79
|
+
'This command is similar to `review`, but default content provider is `gh`. ' +
|
80
|
+
'(assuming that GH cli is installed and authenticated for current project')
|
81
|
+
.argument('<prId>', 'Pull request ID to review.')
|
82
|
+
.argument('[requirementsId]', 'Optional requirements ID argument to retrieve requirements with requirements provider')
|
83
|
+
.addOption(new Option('-p, --requirements-provider <requirementsProvider>', 'Requirements provider for this review.').choices(Object.keys(REQUIREMENTS_PROVIDERS)))
|
84
|
+
.option('-f, --file [files...]', 'Input files. Content of these files will be added BEFORE the diff, but after requirements')
|
85
|
+
.action(async (prId, requirementsId, options) => {
|
86
|
+
const { initConfig } = await import('#src/config.js');
|
87
|
+
await initConfig();
|
88
|
+
const systemMessage = [
|
89
|
+
readBackstory(),
|
90
|
+
readGuidelines(slothContext.config.projectGuidelines),
|
91
|
+
readReviewInstructions(slothContext.config.projectReviewInstructions),
|
92
|
+
];
|
93
|
+
const content = [];
|
94
|
+
const requirementsProvider = options.requirementsProvider ??
|
95
|
+
context.config?.pr?.requirementsProvider ??
|
96
|
+
context.config?.requirementsProvider;
|
97
|
+
// Handle requirements
|
98
|
+
const requirements = await getRequirementsFromProvider(requirementsProvider, requirementsId);
|
99
|
+
if (requirements) {
|
100
|
+
content.push(requirements);
|
101
|
+
}
|
102
|
+
if (options.file) {
|
103
|
+
content.push(readMultipleFilesFromCurrentDir(options.file));
|
104
|
+
}
|
105
|
+
// Get PR diff using the 'gh' provider
|
106
|
+
const providerPath = `#src/providers/${CONTENT_PROVIDERS['gh']}`;
|
107
|
+
const { get } = await import(providerPath);
|
108
|
+
content.push(await get(null, prId));
|
109
|
+
const { review } = await import('#src/modules/reviewModule.js');
|
110
|
+
// TODO make the prefix configurable
|
111
|
+
// TODO consider including requirements id
|
112
|
+
// TODO sanitize prId
|
113
|
+
await review(`gth-PR-${prId}-review`, systemMessage.join('\n'), content.join('\n'));
|
114
|
+
});
|
115
|
+
async function getRequirementsFromProvider(requirementsProvider, requirementsId) {
|
116
|
+
return getFromProvider(requirementsProvider, requirementsId, (context.config?.requirementsProviderConfig ?? {})[requirementsProvider], REQUIREMENTS_PROVIDERS);
|
117
|
+
}
|
118
|
+
async function getContentFromProvider(contentProvider, contentId) {
|
119
|
+
return getFromProvider(contentProvider, contentId, (context.config?.contentProviderConfig ?? {})[contentProvider], CONTENT_PROVIDERS);
|
120
|
+
}
|
121
|
+
async function getFromProvider(provider, id,
|
122
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
123
|
+
config, legitPredefinedProviders) {
|
124
|
+
if (typeof provider === 'string') {
|
125
|
+
// Use one of the predefined providers
|
126
|
+
if (legitPredefinedProviders[provider]) {
|
127
|
+
const providerPath = `#src/providers/${legitPredefinedProviders[provider]}`;
|
128
|
+
const { get } = await import(providerPath);
|
129
|
+
return await get(config, id);
|
130
|
+
}
|
131
|
+
else {
|
132
|
+
displayError(`Unknown provider: ${provider}. Continuing without it.`);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
else if (typeof provider === 'function') {
|
136
|
+
// Type assertion to handle function call
|
137
|
+
return await provider(id);
|
138
|
+
}
|
139
|
+
return '';
|
140
|
+
}
|
141
|
+
}
|
142
|
+
//# sourceMappingURL=reviewCommand.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"reviewCommand.js","sourceRoot":"","sources":["../../src/commands/reviewCommand.ts"],"names":[],"mappings":"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"}
|