gaunt-sloth-assistant 0.1.4 → 0.2.2

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.
Files changed (128) hide show
  1. package/.prettierrc.json +9 -0
  2. package/README.md +177 -158
  3. package/ROADMAP.md +1 -1
  4. package/dist/commands/askCommand.d.ts +6 -0
  5. package/dist/commands/askCommand.js +26 -0
  6. package/dist/commands/askCommand.js.map +1 -0
  7. package/dist/commands/initCommand.d.ts +6 -0
  8. package/dist/commands/initCommand.js +16 -0
  9. package/dist/commands/initCommand.js.map +1 -0
  10. package/dist/commands/reviewCommand.d.ts +3 -0
  11. package/dist/commands/reviewCommand.js +128 -0
  12. package/dist/commands/reviewCommand.js.map +1 -0
  13. package/dist/config.d.ts +80 -0
  14. package/dist/config.js +178 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/configs/anthropic.d.ts +5 -0
  17. package/{src → dist}/configs/anthropic.js +45 -48
  18. package/dist/configs/anthropic.js.map +1 -0
  19. package/dist/configs/fake.d.ts +3 -0
  20. package/{src → dist}/configs/fake.js +11 -14
  21. package/dist/configs/fake.js.map +1 -0
  22. package/dist/configs/groq.d.ts +4 -0
  23. package/{src → dist}/configs/groq.js +10 -13
  24. package/dist/configs/groq.js.map +1 -0
  25. package/dist/configs/types.d.ts +14 -0
  26. package/dist/configs/types.js +2 -0
  27. package/dist/configs/types.js.map +1 -0
  28. package/dist/configs/vertexai.d.ts +4 -0
  29. package/{src → dist}/configs/vertexai.js +44 -47
  30. package/dist/configs/vertexai.js.map +1 -0
  31. package/dist/consoleUtils.d.ts +6 -0
  32. package/{src → dist}/consoleUtils.js +10 -15
  33. package/dist/consoleUtils.js.map +1 -0
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.js +17 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/modules/questionAnsweringModule.d.ts +18 -0
  38. package/{src → dist}/modules/questionAnsweringModule.js +72 -82
  39. package/dist/modules/questionAnsweringModule.js.map +1 -0
  40. package/dist/modules/reviewModule.d.ts +4 -0
  41. package/{src → dist}/modules/reviewModule.js +25 -35
  42. package/dist/modules/reviewModule.js.map +1 -0
  43. package/dist/modules/types.d.ts +18 -0
  44. package/dist/modules/types.js +2 -0
  45. package/dist/modules/types.js.map +1 -0
  46. package/dist/prompt.d.ts +7 -0
  47. package/dist/prompt.js +32 -0
  48. package/dist/prompt.js.map +1 -0
  49. package/dist/providers/file.d.ts +8 -0
  50. package/dist/providers/file.js +20 -0
  51. package/dist/providers/file.js.map +1 -0
  52. package/dist/providers/ghPrDiffProvider.d.ts +8 -0
  53. package/dist/providers/ghPrDiffProvider.js +16 -0
  54. package/dist/providers/ghPrDiffProvider.js.map +1 -0
  55. package/dist/providers/jiraIssueLegacyAccessTokenProvider.d.ts +8 -0
  56. package/dist/providers/jiraIssueLegacyAccessTokenProvider.js +62 -0
  57. package/dist/providers/jiraIssueLegacyAccessTokenProvider.js.map +1 -0
  58. package/dist/providers/jiraIssueLegacyProvider.d.ts +8 -0
  59. package/dist/providers/jiraIssueLegacyProvider.js +74 -0
  60. package/dist/providers/jiraIssueLegacyProvider.js.map +1 -0
  61. package/dist/providers/jiraIssueProvider.d.ts +11 -0
  62. package/dist/providers/jiraIssueProvider.js +96 -0
  63. package/dist/providers/jiraIssueProvider.js.map +1 -0
  64. package/dist/providers/text.d.ts +8 -0
  65. package/dist/providers/text.js +10 -0
  66. package/dist/providers/text.js.map +1 -0
  67. package/dist/providers/types.d.ts +21 -0
  68. package/dist/providers/types.js +2 -0
  69. package/dist/providers/types.js.map +1 -0
  70. package/dist/systemUtils.d.ts +22 -0
  71. package/dist/systemUtils.js +36 -0
  72. package/dist/systemUtils.js.map +1 -0
  73. package/dist/utils.d.ts +49 -0
  74. package/{src → dist}/utils.js +73 -60
  75. package/dist/utils.js.map +1 -0
  76. package/docs/CONFIGURATION.md +95 -6
  77. package/docs/RELEASE-HOWTO.md +1 -1
  78. package/eslint.config.js +99 -21
  79. package/index.js +10 -27
  80. package/package.json +26 -15
  81. package/src/commands/askCommand.ts +34 -0
  82. package/src/commands/initCommand.ts +19 -0
  83. package/src/commands/reviewCommand.ts +209 -0
  84. package/src/config.ts +266 -0
  85. package/src/configs/anthropic.ts +55 -0
  86. package/src/configs/fake.ts +15 -0
  87. package/src/configs/groq.ts +54 -0
  88. package/src/configs/vertexai.ts +53 -0
  89. package/src/consoleUtils.ts +33 -0
  90. package/src/index.ts +21 -0
  91. package/src/modules/questionAnsweringModule.ts +97 -0
  92. package/src/modules/reviewModule.ts +81 -0
  93. package/src/modules/types.ts +23 -0
  94. package/src/prompt.ts +39 -0
  95. package/src/providers/file.ts +24 -0
  96. package/src/providers/ghPrDiffProvider.ts +20 -0
  97. package/src/providers/jiraIssueLegacyProvider.ts +103 -0
  98. package/src/providers/jiraIssueProvider.ts +133 -0
  99. package/src/providers/text.ts +14 -0
  100. package/src/providers/types.ts +24 -0
  101. package/src/systemUtils.ts +52 -0
  102. package/src/utils.ts +225 -0
  103. package/tsconfig.json +24 -0
  104. package/vitest.config.ts +13 -0
  105. package/.eslint.config.mjs +0 -72
  106. package/.github/dependabot.yml +0 -11
  107. package/.github/workflows/ci.yml +0 -33
  108. package/spec/.gsloth.config.js +0 -22
  109. package/spec/.gsloth.config.json +0 -25
  110. package/spec/askCommand.spec.js +0 -92
  111. package/spec/config.spec.js +0 -421
  112. package/spec/initCommand.spec.js +0 -55
  113. package/spec/predefinedConfigs.spec.js +0 -100
  114. package/spec/questionAnsweringModule.spec.js +0 -137
  115. package/spec/reviewCommand.spec.js +0 -222
  116. package/spec/reviewModule.spec.js +0 -28
  117. package/spec/support/jasmine.mjs +0 -14
  118. package/src/commands/askCommand.js +0 -27
  119. package/src/commands/initCommand.js +0 -17
  120. package/src/commands/reviewCommand.js +0 -154
  121. package/src/config.js +0 -177
  122. package/src/prompt.js +0 -34
  123. package/src/providers/file.js +0 -19
  124. package/src/providers/ghPrDiffProvider.js +0 -11
  125. package/src/providers/jiraIssueLegacyAccessTokenProvider.js +0 -84
  126. package/src/providers/text.js +0 -6
  127. package/src/systemUtils.js +0 -32
  128. /package/{.gsloth.preamble.internal.md → .gsloth.backstory.md} +0 -0
@@ -0,0 +1,9 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "tabWidth": 2,
5
+ "printWidth": 100,
6
+ "trailingComma": "es5",
7
+ "arrowParens": "always",
8
+ "endOfLine": "lf"
9
+ }
package/README.md CHANGED
@@ -1,158 +1,177 @@
1
- # Gaunt Sloth Assistant
2
- [![Tests and Lint](https://github.com/andruhon/gaunt-sloth-assistant/actions/workflows/ci.yml/badge.svg?event=push)](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
- Example configuration setting up JIRA integration using a legacy API token for both `review` and `pr` commands.
64
- Make sure you use your actual company domain in `baseUrl` and your personal legacy `token`.
65
-
66
- A legacy token can be acquired from `Atlassian Account Settings -> Security -> Create and manage API tokens`.
67
-
68
- ```json
69
- {
70
- "llm": {"type": "vertexai", "model": "gemini-2.5-pro-exp-03-25"},
71
- "requirementsProvider": "jira-legacy",
72
- "requirementsProviderConfig": {
73
- "jira-legacy": {
74
- "username": "user@yourcompany.com",
75
- "token": "YOUR_JIRA_LEGACY_TOKEN",
76
- "baseUrl": "https://yourcompany.atlassian.net/rest/api/2/issue/"
77
- }
78
- }
79
- }
80
- ```
81
-
82
- ### Review any Diff
83
- ```shell
84
- git --no-pager diff origin/master...yourgitcommithash | gsloth review
85
- ```
86
- (helpful to review a subset of PR)
87
-
88
- Review current local changes:
89
- ```shell
90
- git --no-pager diff | gsloth review
91
- ```
92
-
93
- ### Question Answering
94
- ```shell
95
- gsloth ask "which types of primitives are available in JavaScript?"
96
- ```
97
-
98
- ```shell
99
- gsloth ask "Please have a look at this file" -f index.js
100
- ```
101
-
102
- Multiple files may be provided as well
103
-
104
- ```shell
105
- gsloth ask "Please have a look at these files" -f index.js test.js
106
- ```
107
-
108
- ## Installation
109
-
110
- Tested with Node 22 LTS.
111
-
112
- ### NPM
113
- ```shell
114
- npm install gaunt-sloth-assistant -g
115
- ```
116
-
117
- ## Configuration
118
-
119
- > 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.preamble.review.md`.
120
- > Global configuration to invoke gsloth anywhere is in [ROADMAP](ROADMAP.md).
121
-
122
- Configuration can be created with `gsloth init [vendor]` command.
123
- Currently, vertexai, anthropic and groq can be configured with `gsloth init [vendor]`.
124
-
125
- More detailed information on configuration can be found in [CONFIGURATION.md](./docs/CONFIGURATION.md)
126
-
127
- ### Google Vertex AI
128
- ```shell
129
- cd ./your-project
130
- gsloth init vertexai
131
- gcloud auth login
132
- gcloud auth application-default login
133
- ```
134
-
135
- ### Anthropic
136
-
137
- ```shell
138
- cd ./your-project
139
- gsloth init anthropic
140
- ```
141
-
142
- Make sure you either define `ANTHROPIC_API_KEY` environment variable or edit your configuration file and set up your key.
143
-
144
- ### Groq
145
- ```shell
146
- cd ./your-project
147
- gsloth init groq
148
- ```
149
- Make sure you either define `GROQ_API_KEY` environment variable or edit your configuration file and set up your key.
150
-
151
- ### Other AI providers
152
- Any other AI provider supported by Langchain.js can be configured with js [Config](./docs/CONFIGURATION.md).
153
-
154
- ## Building from repo
155
- See [DEVELOPMENT.md](./docs/DEVELOPMENT.md)
156
-
157
- ## License
158
- License is [MIT](https://opensource.org/license/mit). See [LICENSE](LICENSE)
1
+ # Gaunt Sloth Assistant
2
+ [![Tests and Lint](https://github.com/andruhon/gaunt-sloth-assistant/actions/workflows/ci.yml/badge.svg?event=push)](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.preamble.review.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
- - [ ] Add JIRA legacy token integration plugin
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,6 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Adds the ask command to the program
4
+ * @param program - The commander program
5
+ */
6
+ export declare function askCommand(program: Command): void;
@@ -0,0 +1,26 @@
1
+ import { readInternalPreamble } from '#src/prompt.js';
2
+ import { readMultipleFilesFromCurrentDir } from '#src/utils.js';
3
+ import { initConfig } 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 = [readInternalPreamble()];
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
+ await askQuestion('sloth-ASK', preamble.join('\n'), content.join('\n'));
24
+ });
25
+ }
26
+ //# sourceMappingURL=askCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"askCommand.js","sourceRoot":"","sources":["../../src/commands/askCommand.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,+BAA+B,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAM5C;;;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,oBAAoB,EAAE,CAAC,CAAC;QAC1C,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,MAAM,WAAW,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Adds the init command to the program
4
+ * @param program - The commander program
5
+ */
6
+ export declare function initCommand(program: Command): void;
@@ -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,3 @@
1
+ import { Command } from 'commander';
2
+ import type { SlothContext } from '#src/config.js';
3
+ export declare function reviewCommand(program: Command, context: SlothContext): void;
@@ -0,0 +1,128 @@
1
+ import { Option } from 'commander';
2
+ import { USER_PROJECT_REVIEW_PREAMBLE } from '#src/config.js';
3
+ import { readInternalPreamble, readPreamble } from '#src/prompt.js';
4
+ import { readMultipleFilesFromCurrentDir } from '#src/utils.js';
5
+ import { displayError } from '#src/consoleUtils.js';
6
+ /**
7
+ * Requirements providers. Expected to be in `.providers/` dir
8
+ */
9
+ const REQUIREMENTS_PROVIDERS = {
10
+ 'jira-legacy': 'jiraIssueLegacyProvider.js',
11
+ jira: 'jiraIssueProvider.js',
12
+ text: 'text.js',
13
+ file: 'file.js',
14
+ };
15
+ /**
16
+ * Content providers. Expected to be in `.providers/` dir
17
+ */
18
+ const CONTENT_PROVIDERS = {
19
+ gh: 'ghPrDiffProvider.js',
20
+ text: 'text.js',
21
+ file: 'file.js',
22
+ };
23
+ export function reviewCommand(program, context) {
24
+ program
25
+ .command('review')
26
+ .description('Review provided diff or other content')
27
+ .argument('[contentId]', 'Optional content ID argument to retrieve content with content provider')
28
+ .alias('r')
29
+ // TODO add provider to get results of git --no-pager diff
30
+ .option('-f, --file [files...]', 'Input files. Content of these files will be added BEFORE the diff, but after requirements')
31
+ // TODO figure out what to do with this (we probably want to merge it with requirementsId)?
32
+ .option('-r, --requirements <requirements>', 'Requirements for this review.')
33
+ .addOption(new Option('-p, --requirements-provider <requirementsProvider>', 'Requirements provider for this review.').choices(Object.keys(REQUIREMENTS_PROVIDERS)))
34
+ .addOption(new Option('--content-provider <contentProvider>', 'Content provider').choices(Object.keys(CONTENT_PROVIDERS)))
35
+ .option('-m, --message <message>', 'Extra message to provide just before the content')
36
+ .action(async (contentId, options) => {
37
+ const { initConfig } = await import('#src/config.js');
38
+ await initConfig();
39
+ const preamble = [readInternalPreamble(), readPreamble(USER_PROJECT_REVIEW_PREAMBLE)];
40
+ const content = [];
41
+ const requirementsId = options.requirements;
42
+ const requirementsProvider = options.requirementsProvider ??
43
+ context.config?.review?.requirementsProvider ??
44
+ context.config?.requirementsProvider;
45
+ const contentProvider = options.contentProvider ??
46
+ context.config?.review?.contentProvider ??
47
+ context.config?.contentProvider;
48
+ // TODO consider calling these in parallel
49
+ const requirements = await getRequirementsFromProvider(requirementsProvider, requirementsId);
50
+ if (requirements) {
51
+ content.push(requirements);
52
+ }
53
+ const providedContent = await getContentFromProvider(contentProvider, contentId);
54
+ if (providedContent) {
55
+ content.push(providedContent);
56
+ }
57
+ if (options.file) {
58
+ content.push(readMultipleFilesFromCurrentDir(options.file));
59
+ }
60
+ if (context.stdin) {
61
+ content.push(context.stdin);
62
+ }
63
+ if (options.message) {
64
+ content.push(options.message);
65
+ }
66
+ const { review } = await import('#src/modules/reviewModule.js');
67
+ await review('sloth-DIFF-review', preamble.join('\n'), content.join('\n'));
68
+ });
69
+ program
70
+ .command('pr')
71
+ .description('Review provided Pull Request in current directory. ' +
72
+ 'This command is similar to `review`, but default content provider is `gh`. ' +
73
+ '(assuming that GH cli is installed and authenticated for current project')
74
+ .argument('<prId>', 'Pull request ID to review.')
75
+ .argument('[requirementsId]', 'Optional requirements ID argument to retrieve requirements with requirements provider')
76
+ .addOption(new Option('-p, --requirements-provider <requirementsProvider>', 'Requirements provider for this review.').choices(Object.keys(REQUIREMENTS_PROVIDERS)))
77
+ .option('-f, --file [files...]', 'Input files. Content of these files will be added BEFORE the diff, but after requirements')
78
+ .action(async (prId, requirementsId, options) => {
79
+ const { initConfig } = await import('#src/config.js');
80
+ await initConfig();
81
+ const preamble = [readInternalPreamble(), readPreamble(USER_PROJECT_REVIEW_PREAMBLE)];
82
+ const content = [];
83
+ const requirementsProvider = options.requirementsProvider ??
84
+ context.config?.pr?.requirementsProvider ??
85
+ context.config?.requirementsProvider;
86
+ // Handle requirements
87
+ const requirements = await getRequirementsFromProvider(requirementsProvider, requirementsId);
88
+ if (requirements) {
89
+ content.push(requirements);
90
+ }
91
+ if (options.file) {
92
+ content.push(readMultipleFilesFromCurrentDir(options.file));
93
+ }
94
+ // Get PR diff using the 'gh' provider
95
+ const providerPath = `#src/providers/${CONTENT_PROVIDERS['gh']}`;
96
+ const { get } = await import(providerPath);
97
+ content.push(await get(null, prId));
98
+ const { review } = await import('#src/modules/reviewModule.js');
99
+ await review(`sloth-PR-${prId}-review`, preamble.join('\n'), content.join('\n'));
100
+ });
101
+ async function getRequirementsFromProvider(requirementsProvider, requirementsId) {
102
+ return getFromProvider(requirementsProvider, requirementsId, (context.config?.requirementsProviderConfig ?? {})[requirementsProvider], REQUIREMENTS_PROVIDERS);
103
+ }
104
+ async function getContentFromProvider(contentProvider, contentId) {
105
+ return getFromProvider(contentProvider, contentId, (context.config?.contentProviderConfig ?? {})[contentProvider], CONTENT_PROVIDERS);
106
+ }
107
+ async function getFromProvider(provider, id,
108
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
109
+ config, legitPredefinedProviders) {
110
+ if (typeof provider === 'string') {
111
+ // Use one of the predefined providers
112
+ if (legitPredefinedProviders[provider]) {
113
+ const providerPath = `#src/providers/${legitPredefinedProviders[provider]}`;
114
+ const { get } = await import(providerPath);
115
+ return await get(config, id);
116
+ }
117
+ else {
118
+ displayError(`Unknown provider: ${provider}. Continuing without it.`);
119
+ }
120
+ }
121
+ else if (typeof provider === 'function') {
122
+ // Type assertion to handle function call
123
+ return await provider(id);
124
+ }
125
+ return '';
126
+ }
127
+ }
128
+ //# sourceMappingURL=reviewCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewCommand.js","sourceRoot":"","sources":["../../src/commands/reviewCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,+BAA+B,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD;;GAEG;AACH,MAAM,sBAAsB,GAAG;IAC7B,aAAa,EAAE,4BAA4B;IAC3C,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;CACP,CAAC;AAIX;;GAEG;AACH,MAAM,iBAAiB,GAAG;IACxB,EAAE,EAAE,qBAAqB;IACzB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;CACP,CAAC;AAiBX,MAAM,UAAU,aAAa,CAAC,OAAgB,EAAE,OAAqB;IACnE,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,uCAAuC,CAAC;SACpD,QAAQ,CACP,aAAa,EACb,wEAAwE,CACzE;SACA,KAAK,CAAC,GAAG,CAAC;QACX,0DAA0D;SACzD,MAAM,CACL,uBAAuB,EACvB,2FAA2F,CAC5F;QACD,2FAA2F;SAC1F,MAAM,CAAC,mCAAmC,EAAE,+BAA+B,CAAC;SAC5E,SAAS,CACR,IAAI,MAAM,CACR,oDAAoD,EACpD,wCAAwC,CACzC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAC/C;SACA,SAAS,CACR,IAAI,MAAM,CAAC,sCAAsC,EAAE,mBAAmB,CAAC,CAAC,OAAO,CAC7E,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAC/B,CACF;SACA,MAAM,CAAC,yBAAyB,EAAE,kDAAkD,CAAC;SACrF,MAAM,CAAC,KAAK,EAAE,SAA6B,EAAE,OAA6B,EAAE,EAAE;QAC7E,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACtD,MAAM,UAAU,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,CAAC,oBAAoB,EAAE,EAAE,YAAY,CAAC,4BAA4B,CAAC,CAAC,CAAC;QACtF,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;QAC5C,MAAM,oBAAoB,GACxB,OAAO,CAAC,oBAAoB;YAC3B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,oBAA6D;YACrF,OAAO,CAAC,MAAM,EAAE,oBAA6D,CAAC;QACjF,MAAM,eAAe,GACnB,OAAO,CAAC,eAAe;YACtB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,eAAmD;YAC3E,OAAO,CAAC,MAAM,EAAE,eAAmD,CAAC;QAEvE,0CAA0C;QAC1C,MAAM,YAAY,GAAG,MAAM,2BAA2B,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAC;QAC7F,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7B,CAAC;QAED,MAAM,eAAe,GAAG,MAAM,sBAAsB,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;QACjF,IAAI,eAAe,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;QAChE,MAAM,MAAM,CAAC,mBAAmB,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,IAAI,CAAC;SACb,WAAW,CACV,qDAAqD;QACnD,6EAA6E;QAC7E,0EAA0E,CAC7E;SACA,QAAQ,CAAC,QAAQ,EAAE,4BAA4B,CAAC;SAChD,QAAQ,CACP,kBAAkB,EAClB,uFAAuF,CACxF;SACA,SAAS,CACR,IAAI,MAAM,CACR,oDAAoD,EACpD,wCAAwC,CACzC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAC/C;SACA,MAAM,CACL,uBAAuB,EACvB,2FAA2F,CAC5F;SACA,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,cAAkC,EAAE,OAAyB,EAAE,EAAE;QAC5F,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACtD,MAAM,UAAU,EAAE,CAAC;QAEnB,MAAM,QAAQ,GAAG,CAAC,oBAAoB,EAAE,EAAE,YAAY,CAAC,4BAA4B,CAAC,CAAC,CAAC;QACtF,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,oBAAoB,GACxB,OAAO,CAAC,oBAAoB;YAC3B,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,oBAA6D;YACjF,OAAO,CAAC,MAAM,EAAE,oBAA6D,CAAC;QAEjF,sBAAsB;QACtB,MAAM,YAAY,GAAG,MAAM,2BAA2B,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAC;QAC7F,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7B,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9D,CAAC;QAED,sCAAsC;QACtC,MAAM,YAAY,GAAG,kBAAkB,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;QACjE,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAEpC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;QAChE,MAAM,MAAM,CAAC,YAAY,IAAI,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IAEL,KAAK,UAAU,2BAA2B,CACxC,oBAA0D,EAC1D,cAAkC;QAElC,OAAO,eAAe,CACpB,oBAAoB,EACpB,cAAc,EACd,CAAC,OAAO,CAAC,MAAM,EAAE,0BAA0B,IAAI,EAAE,CAAC,CAAC,oBAA8B,CAAC,EAClF,sBAAsB,CACvB,CAAC;IACJ,CAAC;IAED,KAAK,UAAU,sBAAsB,CACnC,eAAgD,EAChD,SAA6B;QAE7B,OAAO,eAAe,CACpB,eAAe,EACf,SAAS,EACT,CAAC,OAAO,CAAC,MAAM,EAAE,qBAAqB,IAAI,EAAE,CAAC,CAAC,eAAyB,CAAC,EACxE,iBAAiB,CAClB,CAAC;IACJ,CAAC;IAED,KAAK,UAAU,eAAe,CAC5B,QAAoE,EACpE,EAAsB;IACtB,8DAA8D;IAC9D,MAAW,EACX,wBAAkF;QAElF,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,sCAAsC;YACtC,IAAI,wBAAwB,CAAC,QAAiD,CAAC,EAAE,CAAC;gBAChF,MAAM,YAAY,GAAG,kBAAkB,wBAAwB,CAAC,QAAiD,CAAC,EAAE,CAAC;gBACrH,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;gBAC3C,OAAO,MAAM,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,YAAY,CAAC,qBAAqB,QAAQ,0BAA0B,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;YAC1C,yCAAyC;YACzC,OAAO,MAAO,QAAwD,CAAC,EAAE,CAAC,CAAC;QAC7E,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { LanguageModelLike } from '@langchain/core/language_models/base';
2
+ export interface SlothConfig extends BaseSlothConfig {
3
+ llm: LanguageModelLike;
4
+ contentProvider: string;
5
+ requirementsProvider: string;
6
+ commands: {
7
+ pr: {
8
+ contentProvider: string;
9
+ };
10
+ };
11
+ }
12
+ /**
13
+ * Raw, unprocessed sloth config
14
+ */
15
+ export interface RawSlothConfig extends BaseSlothConfig {
16
+ llm: LLMConfig;
17
+ }
18
+ /**
19
+ * Do not export this one
20
+ */
21
+ interface BaseSlothConfig {
22
+ llm: unknown;
23
+ contentProvider?: string;
24
+ requirementsProvider?: string;
25
+ commands?: {
26
+ pr: {
27
+ contentProvider: string;
28
+ };
29
+ };
30
+ review?: {
31
+ requirementsProvider?: string;
32
+ contentProvider?: string;
33
+ };
34
+ pr?: {
35
+ requirementsProvider?: string;
36
+ };
37
+ requirementsProviderConfig?: Record<string, unknown>;
38
+ contentProviderConfig?: Record<string, unknown>;
39
+ }
40
+ /**
41
+ * @deprecated
42
+ * this object has blurred responsibility lines and bad name.
43
+ */
44
+ export interface SlothContext {
45
+ config: SlothConfig;
46
+ stdin: string;
47
+ session: {
48
+ configurable: {
49
+ thread_id: string;
50
+ };
51
+ };
52
+ }
53
+ export interface LLMConfig extends Record<string, unknown> {
54
+ type: string;
55
+ model: string;
56
+ }
57
+ export declare const USER_PROJECT_CONFIG_JS = ".gsloth.config.js";
58
+ export declare const USER_PROJECT_CONFIG_JSON = ".gsloth.config.json";
59
+ export declare const USER_PROJECT_CONFIG_MJS = ".gsloth.config.mjs";
60
+ export declare const GSLOTH_BACKSTORY = ".gsloth.backstory.md";
61
+ export declare const USER_PROJECT_REVIEW_PREAMBLE = ".gsloth.preamble.review.md";
62
+ export declare const availableDefaultConfigs: readonly ["vertexai", "anthropic", "groq"];
63
+ export type ConfigType = (typeof availableDefaultConfigs)[number];
64
+ export declare const DEFAULT_CONFIG: Partial<SlothConfig>;
65
+ /**
66
+ * @deprecated
67
+ * this object has blurred responsibility lines and bad name.
68
+ * TODO this should be reworked to something more robust
69
+ */
70
+ export declare const slothContext: SlothContext;
71
+ export declare function initConfig(): Promise<void>;
72
+ export declare function tryJsonConfig(jsonConfig: RawSlothConfig): Promise<void>;
73
+ export declare function createProjectConfig(configType: string): Promise<void>;
74
+ export declare function writeProjectReviewPreamble(): void;
75
+ /**
76
+ * @deprecated test only
77
+ * TODO should be gone together with slothContext itself
78
+ */
79
+ export declare function reset(): void;
80
+ export {};