gaunt-sloth-assistant 0.4.2 → 0.5.1
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/.claude/settings.local.json +15 -0
- package/.gsloth.backstory.md +0 -0
- package/.gsloth.guidelines.md +0 -0
- package/.gsloth.review.md +0 -0
- package/.gsloth.system.md +10 -0
- package/.prettierrc.json +0 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +0 -0
- package/README.md +11 -1
- package/ROADMAP.md +0 -0
- package/assets/gaunt-sloth-logo.png +0 -0
- package/assets/release-notes/v0_4_0.md +0 -0
- package/assets/release-notes/v0_5_0.md +10 -0
- package/assets/release-notes/v0_5_1.md +47 -0
- package/dist/commands/askCommand.d.ts +0 -0
- package/dist/commands/askCommand.js +9 -5
- package/dist/commands/askCommand.js.map +1 -1
- package/dist/commands/commandUtils.d.ts +25 -0
- package/dist/commands/commandUtils.js +48 -0
- package/dist/commands/commandUtils.js.map +1 -0
- package/dist/commands/initCommand.d.ts +0 -0
- package/dist/commands/initCommand.js +0 -0
- package/dist/commands/initCommand.js.map +0 -0
- package/dist/commands/prCommand.d.ts +2 -0
- package/dist/commands/prCommand.js +52 -0
- package/dist/commands/prCommand.js.map +1 -0
- package/dist/commands/reviewCommand.d.ts +1 -2
- package/dist/commands/reviewCommand.js +17 -98
- package/dist/commands/reviewCommand.js.map +1 -1
- package/dist/config.d.ts +22 -41
- package/dist/config.js +107 -88
- package/dist/config.js.map +1 -1
- package/dist/configs/anthropic.d.ts +0 -0
- package/dist/configs/anthropic.js +0 -0
- package/dist/configs/anthropic.js.map +0 -0
- package/dist/configs/fake.d.ts +0 -0
- package/dist/configs/fake.js +0 -0
- package/dist/configs/fake.js.map +0 -0
- package/dist/configs/groq.d.ts +0 -0
- package/dist/configs/groq.js +0 -0
- package/dist/configs/groq.js.map +0 -0
- package/dist/configs/vertexai.d.ts +0 -0
- package/dist/configs/vertexai.js +0 -0
- package/dist/configs/vertexai.js.map +0 -0
- package/dist/consoleUtils.d.ts +0 -0
- package/dist/consoleUtils.js +0 -0
- package/dist/consoleUtils.js.map +0 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -0
- package/dist/filePathUtils.d.ts +0 -0
- package/dist/filePathUtils.js +0 -0
- package/dist/filePathUtils.js.map +0 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/llmUtils.d.ts +2 -2
- package/dist/llmUtils.js +128 -28
- package/dist/llmUtils.js.map +1 -1
- package/dist/modules/questionAnsweringModule.d.ts +2 -1
- package/dist/modules/questionAnsweringModule.js +7 -8
- package/dist/modules/questionAnsweringModule.js.map +1 -1
- package/dist/modules/reviewModule.d.ts +2 -1
- package/dist/modules/reviewModule.js +7 -11
- package/dist/modules/reviewModule.js.map +1 -1
- package/dist/modules/types.d.ts +0 -0
- package/dist/modules/types.js +0 -0
- package/dist/modules/types.js.map +0 -0
- package/dist/prompt.d.ts +1 -0
- package/dist/prompt.js +4 -1
- package/dist/prompt.js.map +1 -1
- package/dist/providers/file.d.ts +0 -0
- package/dist/providers/file.js +0 -0
- package/dist/providers/file.js.map +0 -0
- package/dist/providers/ghIssueProvider.d.ts +0 -0
- package/dist/providers/ghIssueProvider.js +3 -1
- package/dist/providers/ghIssueProvider.js.map +1 -1
- package/dist/providers/ghPrDiffProvider.d.ts +0 -0
- package/dist/providers/ghPrDiffProvider.js +3 -1
- package/dist/providers/ghPrDiffProvider.js.map +1 -1
- package/dist/providers/jiraIssueLegacyProvider.d.ts +0 -0
- package/dist/providers/jiraIssueLegacyProvider.js +0 -0
- package/dist/providers/jiraIssueLegacyProvider.js.map +0 -0
- package/dist/providers/jiraIssueProvider.d.ts +0 -0
- package/dist/providers/jiraIssueProvider.js +3 -1
- package/dist/providers/jiraIssueProvider.js.map +1 -1
- package/dist/providers/text.d.ts +0 -0
- package/dist/providers/text.js +0 -0
- package/dist/providers/text.js.map +0 -0
- package/dist/providers/types.d.ts +0 -0
- package/dist/providers/types.js +0 -0
- package/dist/providers/types.js.map +0 -0
- package/dist/systemUtils.d.ts +0 -0
- package/dist/systemUtils.js +0 -0
- package/dist/systemUtils.js.map +0 -0
- package/dist/utils.d.ts +0 -0
- package/dist/utils.js +0 -0
- package/dist/utils.js.map +0 -0
- package/docs/CONFIGURATION.md +60 -26
- package/docs/DEVELOPMENT.md +0 -0
- package/docs/RELEASE-HOWTO.md +0 -0
- package/eslint.config.js +0 -0
- package/maintenance/doc-maintenance.md +0 -0
- package/package.json +11 -7
- package/src/commands/askCommand.ts +9 -5
- package/src/commands/commandUtils.ts +77 -0
- package/src/commands/initCommand.ts +0 -0
- package/src/commands/prCommand.ts +93 -0
- package/src/commands/reviewCommand.ts +33 -155
- package/src/config.ts +128 -128
- package/src/configs/anthropic.ts +0 -0
- package/src/configs/fake.ts +0 -0
- package/src/configs/groq.ts +0 -0
- package/src/configs/vertexai.ts +0 -0
- package/src/consoleUtils.ts +0 -0
- package/src/constants.ts +7 -0
- package/src/filePathUtils.ts +0 -0
- package/src/index.ts +4 -2
- package/src/llmUtils.ts +149 -36
- package/src/modules/questionAnsweringModule.ts +9 -13
- package/src/modules/reviewModule.ts +14 -11
- package/src/modules/types.ts +0 -0
- package/src/prompt.ts +5 -1
- package/src/providers/file.ts +0 -0
- package/src/providers/ghIssueProvider.ts +3 -1
- package/src/providers/ghPrDiffProvider.ts +3 -1
- package/src/providers/jiraIssueLegacyProvider.ts +0 -0
- package/src/providers/jiraIssueProvider.ts +5 -1
- package/src/providers/text.ts +0 -0
- package/src/providers/types.ts +0 -0
- package/src/systemUtils.ts +0 -0
- package/src/utils.ts +0 -0
- package/tsconfig.json +0 -0
- package/vitest-it.config.ts +0 -0
- package/vitest.config.ts +0 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
import { Command, Option } from 'commander';
|
2
|
+
import {
|
3
|
+
readBackstory,
|
4
|
+
readGuidelines,
|
5
|
+
readReviewInstructions,
|
6
|
+
readSystemPrompt,
|
7
|
+
} from '#src/prompt.js';
|
8
|
+
import { readMultipleFilesFromCurrentDir } from '#src/utils.js';
|
9
|
+
import {
|
10
|
+
REQUIREMENTS_PROVIDERS,
|
11
|
+
CONTENT_PROVIDERS,
|
12
|
+
type RequirementsProviderType,
|
13
|
+
getRequirementsFromProvider,
|
14
|
+
type ContentProviderType,
|
15
|
+
} from './commandUtils.js';
|
16
|
+
|
17
|
+
interface PrCommandOptions {
|
18
|
+
file?: string[];
|
19
|
+
requirementsProvider?: RequirementsProviderType;
|
20
|
+
}
|
21
|
+
|
22
|
+
export function prCommand(program: Command): void {
|
23
|
+
program
|
24
|
+
.command('pr')
|
25
|
+
.description(
|
26
|
+
'Review provided Pull Request in current directory. ' +
|
27
|
+
'This command is similar to `review`, but default content provider is `github`. ' +
|
28
|
+
'(assuming that GitHub CLI is installed and authenticated for current project'
|
29
|
+
)
|
30
|
+
.argument('<prId>', 'Pull request ID to review.')
|
31
|
+
.argument(
|
32
|
+
'[requirementsId]',
|
33
|
+
'Optional requirements ID argument to retrieve requirements with requirements provider'
|
34
|
+
)
|
35
|
+
.addOption(
|
36
|
+
new Option(
|
37
|
+
'-p, --requirements-provider <requirementsProvider>',
|
38
|
+
'Requirements provider for this review.'
|
39
|
+
).choices(Object.keys(REQUIREMENTS_PROVIDERS))
|
40
|
+
)
|
41
|
+
.option(
|
42
|
+
'-f, --file [files...]',
|
43
|
+
'Input files. Content of these files will be added BEFORE the diff, but after requirements'
|
44
|
+
)
|
45
|
+
.action(async (prId: string, requirementsId: string | undefined, options: PrCommandOptions) => {
|
46
|
+
const { initConfig } = await import('#src/config.js');
|
47
|
+
const config = await initConfig(); // Initialize and get config
|
48
|
+
|
49
|
+
const systemPrompt = readSystemPrompt();
|
50
|
+
const systemMessage = [
|
51
|
+
readBackstory(),
|
52
|
+
readGuidelines(config.projectGuidelines),
|
53
|
+
readReviewInstructions(config.projectReviewInstructions),
|
54
|
+
];
|
55
|
+
if (systemPrompt) {
|
56
|
+
systemMessage.push(systemPrompt);
|
57
|
+
}
|
58
|
+
const content: string[] = [];
|
59
|
+
const requirementsProvider =
|
60
|
+
options.requirementsProvider ??
|
61
|
+
(config?.commands?.pr?.requirementsProvider as RequirementsProviderType | undefined) ??
|
62
|
+
(config?.requirementsProvider as RequirementsProviderType | undefined);
|
63
|
+
|
64
|
+
const contentProvider =
|
65
|
+
(config?.commands?.pr?.contentProvider as ContentProviderType | undefined) ??
|
66
|
+
(config?.contentProvider as ContentProviderType | undefined) ??
|
67
|
+
'github';
|
68
|
+
|
69
|
+
// Handle requirements
|
70
|
+
const requirements = await getRequirementsFromProvider(
|
71
|
+
requirementsProvider,
|
72
|
+
requirementsId,
|
73
|
+
config
|
74
|
+
);
|
75
|
+
if (requirements) {
|
76
|
+
content.push(requirements);
|
77
|
+
}
|
78
|
+
|
79
|
+
if (options.file) {
|
80
|
+
content.push(readMultipleFilesFromCurrentDir(options.file));
|
81
|
+
}
|
82
|
+
|
83
|
+
// Get PR diff using the provider
|
84
|
+
const providerPath = `#src/providers/${CONTENT_PROVIDERS[contentProvider]}`;
|
85
|
+
const { get } = await import(providerPath);
|
86
|
+
content.push(await get(null, prId));
|
87
|
+
|
88
|
+
const { review } = await import('#src/modules/reviewModule.js');
|
89
|
+
// TODO consider including requirements id
|
90
|
+
// TODO sanitize prId
|
91
|
+
await review(`PR-${prId}`, systemMessage.join('\n'), content.join('\n'), config, 'pr');
|
92
|
+
});
|
93
|
+
}
|
@@ -1,36 +1,20 @@
|
|
1
1
|
import { Command, Option } from 'commander';
|
2
|
-
import
|
3
|
-
|
4
|
-
|
2
|
+
import {
|
3
|
+
readBackstory,
|
4
|
+
readGuidelines,
|
5
|
+
readReviewInstructions,
|
6
|
+
readSystemPrompt,
|
7
|
+
} from '#src/prompt.js';
|
5
8
|
import { readMultipleFilesFromCurrentDir } from '#src/utils.js';
|
6
|
-
import { displayError } from '#src/consoleUtils.js';
|
7
9
|
import { getStringFromStdin } from '#src/systemUtils.js';
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
github: 'ghIssueProvider.js',
|
17
|
-
text: 'text.js',
|
18
|
-
file: 'file.js',
|
19
|
-
} as const;
|
20
|
-
|
21
|
-
type RequirementsProviderType = keyof typeof REQUIREMENTS_PROVIDERS;
|
22
|
-
|
23
|
-
/**
|
24
|
-
* Content providers. Expected to be in `.providers/` dir.
|
25
|
-
* Aliases are mapped to actual providers in this file
|
26
|
-
*/
|
27
|
-
const CONTENT_PROVIDERS = {
|
28
|
-
github: 'ghPrDiffProvider.js',
|
29
|
-
text: 'text.js',
|
30
|
-
file: 'file.js',
|
31
|
-
} as const;
|
32
|
-
|
33
|
-
type ContentProviderType = keyof typeof CONTENT_PROVIDERS;
|
10
|
+
import {
|
11
|
+
REQUIREMENTS_PROVIDERS,
|
12
|
+
CONTENT_PROVIDERS,
|
13
|
+
type RequirementsProviderType,
|
14
|
+
type ContentProviderType,
|
15
|
+
getRequirementsFromProvider,
|
16
|
+
getContentFromProvider,
|
17
|
+
} from './commandUtils.js';
|
34
18
|
|
35
19
|
interface ReviewCommandOptions {
|
36
20
|
file?: string[];
|
@@ -40,12 +24,7 @@ interface ReviewCommandOptions {
|
|
40
24
|
message?: string;
|
41
25
|
}
|
42
26
|
|
43
|
-
|
44
|
-
file?: string[];
|
45
|
-
requirementsProvider?: RequirementsProviderType;
|
46
|
-
}
|
47
|
-
|
48
|
-
export function reviewCommand(program: Command, context: SlothContext): void {
|
27
|
+
export function reviewCommand(program: Command): void {
|
49
28
|
program
|
50
29
|
.command('review')
|
51
30
|
.description('Review provided diff or other content')
|
@@ -75,32 +54,38 @@ export function reviewCommand(program: Command, context: SlothContext): void {
|
|
75
54
|
.option('-m, --message <message>', 'Extra message to provide just before the content')
|
76
55
|
.action(async (contentId: string | undefined, options: ReviewCommandOptions) => {
|
77
56
|
const { initConfig } = await import('#src/config.js');
|
78
|
-
await initConfig();
|
57
|
+
const config = await initConfig(); // Initialize and get config
|
58
|
+
const systemPrompt = readSystemPrompt();
|
79
59
|
const systemMessage = [
|
80
60
|
readBackstory(),
|
81
|
-
readGuidelines(
|
82
|
-
readReviewInstructions(
|
61
|
+
readGuidelines(config.projectGuidelines),
|
62
|
+
readReviewInstructions(config.projectReviewInstructions),
|
83
63
|
];
|
64
|
+
if (systemPrompt) {
|
65
|
+
systemMessage.push(systemPrompt);
|
66
|
+
}
|
84
67
|
const content: string[] = [];
|
85
68
|
const requirementsId = options.requirements;
|
86
69
|
const requirementsProvider =
|
87
70
|
options.requirementsProvider ??
|
88
|
-
(
|
89
|
-
|
90
|
-
| undefined) ??
|
91
|
-
(context.config?.requirementsProvider as RequirementsProviderType | undefined);
|
71
|
+
(config?.commands?.review?.requirementsProvider as RequirementsProviderType | undefined) ??
|
72
|
+
(config?.requirementsProvider as RequirementsProviderType | undefined);
|
92
73
|
const contentProvider =
|
93
74
|
options.contentProvider ??
|
94
|
-
(
|
95
|
-
(
|
75
|
+
(config?.commands?.review?.contentProvider as ContentProviderType | undefined) ??
|
76
|
+
(config?.contentProvider as ContentProviderType | undefined);
|
96
77
|
|
97
78
|
// TODO consider calling these in parallel
|
98
|
-
const requirements = await getRequirementsFromProvider(
|
79
|
+
const requirements = await getRequirementsFromProvider(
|
80
|
+
requirementsProvider,
|
81
|
+
requirementsId,
|
82
|
+
config
|
83
|
+
);
|
99
84
|
if (requirements) {
|
100
85
|
content.push(requirements);
|
101
86
|
}
|
102
87
|
|
103
|
-
const providedContent = await getContentFromProvider(contentProvider, contentId);
|
88
|
+
const providedContent = await getContentFromProvider(contentProvider, contentId, config);
|
104
89
|
if (providedContent) {
|
105
90
|
content.push(providedContent);
|
106
91
|
}
|
@@ -116,113 +101,6 @@ export function reviewCommand(program: Command, context: SlothContext): void {
|
|
116
101
|
content.push(options.message);
|
117
102
|
}
|
118
103
|
const { review } = await import('#src/modules/reviewModule.js');
|
119
|
-
await review('REVIEW', systemMessage.join('\n'), content.join('\n'));
|
120
|
-
});
|
121
|
-
|
122
|
-
program
|
123
|
-
.command('pr')
|
124
|
-
.description(
|
125
|
-
'Review provided Pull Request in current directory. ' +
|
126
|
-
'This command is similar to `review`, but default content provider is `github`. ' +
|
127
|
-
'(assuming that GitHub CLI is installed and authenticated for current project'
|
128
|
-
)
|
129
|
-
.argument('<prId>', 'Pull request ID to review.')
|
130
|
-
.argument(
|
131
|
-
'[requirementsId]',
|
132
|
-
'Optional requirements ID argument to retrieve requirements with requirements provider'
|
133
|
-
)
|
134
|
-
.addOption(
|
135
|
-
new Option(
|
136
|
-
'-p, --requirements-provider <requirementsProvider>',
|
137
|
-
'Requirements provider for this review.'
|
138
|
-
).choices(Object.keys(REQUIREMENTS_PROVIDERS))
|
139
|
-
)
|
140
|
-
.option(
|
141
|
-
'-f, --file [files...]',
|
142
|
-
'Input files. Content of these files will be added BEFORE the diff, but after requirements'
|
143
|
-
)
|
144
|
-
.action(async (prId: string, requirementsId: string | undefined, options: PrCommandOptions) => {
|
145
|
-
const { initConfig } = await import('#src/config.js');
|
146
|
-
await initConfig();
|
147
|
-
|
148
|
-
const systemMessage = [
|
149
|
-
readBackstory(),
|
150
|
-
readGuidelines(slothContext.config.projectGuidelines),
|
151
|
-
readReviewInstructions(slothContext.config.projectReviewInstructions),
|
152
|
-
];
|
153
|
-
const content: string[] = [];
|
154
|
-
const requirementsProvider =
|
155
|
-
options.requirementsProvider ??
|
156
|
-
(context.config?.commands?.pr?.requirementsProvider as
|
157
|
-
| RequirementsProviderType
|
158
|
-
| undefined) ??
|
159
|
-
(context.config?.requirementsProvider as RequirementsProviderType | undefined);
|
160
|
-
|
161
|
-
// Handle requirements
|
162
|
-
const requirements = await getRequirementsFromProvider(requirementsProvider, requirementsId);
|
163
|
-
if (requirements) {
|
164
|
-
content.push(requirements);
|
165
|
-
}
|
166
|
-
|
167
|
-
if (options.file) {
|
168
|
-
content.push(readMultipleFilesFromCurrentDir(options.file));
|
169
|
-
}
|
170
|
-
|
171
|
-
// Get PR diff using the 'github' provider
|
172
|
-
const providerPath = `#src/providers/${CONTENT_PROVIDERS['github']}`;
|
173
|
-
const { get } = await import(providerPath);
|
174
|
-
content.push(await get(null, prId));
|
175
|
-
|
176
|
-
const { review } = await import('#src/modules/reviewModule.js');
|
177
|
-
// TODO consider including requirements id
|
178
|
-
// TODO sanitize prId
|
179
|
-
await review(`PR-${prId}`, systemMessage.join('\n'), content.join('\n'));
|
104
|
+
await review('REVIEW', systemMessage.join('\n'), content.join('\n'), config);
|
180
105
|
});
|
181
|
-
|
182
|
-
async function getRequirementsFromProvider(
|
183
|
-
requirementsProvider: RequirementsProviderType | undefined,
|
184
|
-
requirementsId: string | undefined
|
185
|
-
): Promise<string> {
|
186
|
-
return getFromProvider(
|
187
|
-
requirementsProvider,
|
188
|
-
requirementsId,
|
189
|
-
(context.config?.requirementsProviderConfig ?? {})[requirementsProvider as string],
|
190
|
-
REQUIREMENTS_PROVIDERS
|
191
|
-
);
|
192
|
-
}
|
193
|
-
|
194
|
-
async function getContentFromProvider(
|
195
|
-
contentProvider: ContentProviderType | undefined,
|
196
|
-
contentId: string | undefined
|
197
|
-
): Promise<string> {
|
198
|
-
return getFromProvider(
|
199
|
-
contentProvider,
|
200
|
-
contentId,
|
201
|
-
(context.config?.contentProviderConfig ?? {})[contentProvider as string],
|
202
|
-
CONTENT_PROVIDERS
|
203
|
-
);
|
204
|
-
}
|
205
|
-
|
206
|
-
async function getFromProvider(
|
207
|
-
provider: RequirementsProviderType | ContentProviderType | undefined,
|
208
|
-
id: string | undefined,
|
209
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
210
|
-
config: any,
|
211
|
-
legitPredefinedProviders: typeof REQUIREMENTS_PROVIDERS | typeof CONTENT_PROVIDERS
|
212
|
-
): Promise<string> {
|
213
|
-
if (typeof provider === 'string') {
|
214
|
-
// Use one of the predefined providers
|
215
|
-
if (legitPredefinedProviders[provider as keyof typeof legitPredefinedProviders]) {
|
216
|
-
const providerPath = `#src/providers/${legitPredefinedProviders[provider as keyof typeof legitPredefinedProviders]}`;
|
217
|
-
const { get } = await import(providerPath);
|
218
|
-
return await get(config, id);
|
219
|
-
} else {
|
220
|
-
displayError(`Unknown provider: ${provider}. Continuing without it.`);
|
221
|
-
}
|
222
|
-
} else if (typeof provider === 'function') {
|
223
|
-
// Type assertion to handle function call
|
224
|
-
return await (provider as (id: string | undefined) => Promise<string>)(id);
|
225
|
-
}
|
226
|
-
return '';
|
227
|
-
}
|
228
106
|
}
|