@gaunt-sloth/review 0.0.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/README.md +31 -0
- package/cli.js +63 -0
- package/dist/commands/commandUtils.d.ts +33 -0
- package/dist/commands/commandUtils.js +59 -0
- package/dist/commands/commandUtils.js.map +1 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/GthAgentRunner.d.ts +1 -0
- package/dist/core/GthAgentRunner.js +2 -0
- package/dist/core/GthAgentRunner.js.map +1 -0
- package/dist/core/types.d.ts +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/helpers/jira/jiraClient.d.ts +11 -0
- package/dist/helpers/jira/jiraClient.js +83 -0
- package/dist/helpers/jira/jiraClient.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/reviewRateMiddleware.d.ts +38 -0
- package/dist/middleware/reviewRateMiddleware.js +103 -0
- package/dist/middleware/reviewRateMiddleware.js.map +1 -0
- package/dist/modules/questionAnsweringModule.d.ts +9 -0
- package/dist/modules/questionAnsweringModule.js +49 -0
- package/dist/modules/questionAnsweringModule.js.map +1 -0
- package/dist/modules/reviewModule.d.ts +3 -0
- package/dist/modules/reviewModule.js +87 -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/sources/fileSource.d.ts +8 -0
- package/dist/sources/fileSource.js +20 -0
- package/dist/sources/fileSource.js.map +1 -0
- package/dist/sources/ghIssueSource.d.ts +8 -0
- package/dist/sources/ghIssueSource.js +34 -0
- package/dist/sources/ghIssueSource.js.map +1 -0
- package/dist/sources/ghPrDiffSource.d.ts +8 -0
- package/dist/sources/ghPrDiffSource.js +29 -0
- package/dist/sources/ghPrDiffSource.js.map +1 -0
- package/dist/sources/jiraIssueLegacySource.d.ts +8 -0
- package/dist/sources/jiraIssueLegacySource.js +74 -0
- package/dist/sources/jiraIssueLegacySource.js.map +1 -0
- package/dist/sources/jiraIssueSource.d.ts +11 -0
- package/dist/sources/jiraIssueSource.js +62 -0
- package/dist/sources/jiraIssueSource.js.map +1 -0
- package/dist/sources/textSource.d.ts +8 -0
- package/dist/sources/textSource.js +10 -0
- package/dist/sources/textSource.js.map +1 -0
- package/dist/sources/types.d.ts +33 -0
- package/dist/sources/types.js +2 -0
- package/dist/sources/types.js.map +1 -0
- package/dist/state/artifactStore.d.ts +1 -0
- package/dist/state/artifactStore.js +2 -0
- package/dist/state/artifactStore.js.map +1 -0
- package/dist/utils/ProgressIndicator.d.ts +1 -0
- package/dist/utils/ProgressIndicator.js +2 -0
- package/dist/utils/ProgressIndicator.js.map +1 -0
- package/dist/utils/consoleUtils.d.ts +1 -0
- package/dist/utils/consoleUtils.js +2 -0
- package/dist/utils/consoleUtils.js.map +1 -0
- package/dist/utils/debugUtils.d.ts +1 -0
- package/dist/utils/debugUtils.js +2 -0
- package/dist/utils/debugUtils.js.map +1 -0
- package/dist/utils/fileUtils.d.ts +7 -0
- package/dist/utils/fileUtils.js +20 -0
- package/dist/utils/fileUtils.js.map +1 -0
- package/dist/utils/llmUtils.d.ts +1 -0
- package/dist/utils/llmUtils.js +2 -0
- package/dist/utils/llmUtils.js.map +1 -0
- package/dist/utils/stringUtils.d.ts +1 -0
- package/dist/utils/stringUtils.js +2 -0
- package/dist/utils/stringUtils.js.map +1 -0
- package/dist/utils/systemUtils.d.ts +1 -0
- package/dist/utils/systemUtils.js +2 -0
- package/dist/utils/systemUtils.js.map +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# @gaunt-sloth/review
|
|
2
|
+
|
|
3
|
+
Review and question-answering functionality for Gaunt Sloth.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- Review module (`reviewModule`) — diff and content review orchestration
|
|
8
|
+
- Question answering module (`questionAnsweringModule`)
|
|
9
|
+
- Command utilities (`commandUtils`)
|
|
10
|
+
- Content and requirement sources: `file`, `text`, `ghPrDiff`, `ghIssue`, `jiraIssue`, `jiraIssueLegacy`
|
|
11
|
+
- Jira client
|
|
12
|
+
- Review rate middleware
|
|
13
|
+
|
|
14
|
+
## CLI
|
|
15
|
+
|
|
16
|
+
The package ships a standalone binary `gaunt-sloth-review` for CI-friendly reviews that does not depend on `commander`. This makes it suitable for embedding in pipelines where a minimal footprint is preferred.
|
|
17
|
+
|
|
18
|
+
## Dependencies
|
|
19
|
+
|
|
20
|
+
- `@gaunt-sloth/core` (required)
|
|
21
|
+
- `@gaunt-sloth/tools` (optional peer dependency)
|
|
22
|
+
|
|
23
|
+
No MCP, no A2A, no commander. This is intentional to keep the package lightweight for CI use.
|
|
24
|
+
|
|
25
|
+
## Exports
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
import { reviewModule } from '@gaunt-sloth/review/reviewModule.js';
|
|
29
|
+
import { questionAnsweringModule } from '@gaunt-sloth/review/questionAnsweringModule.js';
|
|
30
|
+
import { commandUtils } from '@gaunt-sloth/review/commandUtils.js';
|
|
31
|
+
```
|
package/cli.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Simple CLI for gaunt-sloth-review
|
|
5
|
+
* Usage: gaunt-sloth-review [pr-number-or-content] [requirements...]
|
|
6
|
+
*
|
|
7
|
+
* When called with a PR number, reviews the specified PR using the configured content provider.
|
|
8
|
+
* When called without arguments, reads diff from stdin via the configured content provider.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { setEntryPoint } from '@gaunt-sloth/core/utils/systemUtils.js';
|
|
12
|
+
setEntryPoint(import.meta.url);
|
|
13
|
+
|
|
14
|
+
import { initConfig } from '@gaunt-sloth/core/config.js';
|
|
15
|
+
import { review } from '#src/modules/reviewModule.js';
|
|
16
|
+
import { displayError } from '@gaunt-sloth/core/utils/consoleUtils.js';
|
|
17
|
+
import { getContentFromSource, getRequirementsFromSource } from '#src/commands/commandUtils.js';
|
|
18
|
+
import { buildSystemMessages } from '@gaunt-sloth/core/utils/llmUtils.js';
|
|
19
|
+
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
|
|
22
|
+
async function main() {
|
|
23
|
+
try {
|
|
24
|
+
const config = await initConfig({});
|
|
25
|
+
|
|
26
|
+
// First arg is content (e.g. PR number), rest are requirements
|
|
27
|
+
const contentArg = args[0];
|
|
28
|
+
const requirementArgs = args.slice(1);
|
|
29
|
+
|
|
30
|
+
// Get content (e.g. PR diff)
|
|
31
|
+
const contentSource = config.commands?.pr?.contentSource || config.contentSource || 'github';
|
|
32
|
+
const content = await getContentFromSource(contentSource, contentArg, config);
|
|
33
|
+
|
|
34
|
+
// Get requirements if provided
|
|
35
|
+
let requirements = '';
|
|
36
|
+
if (requirementArgs.length > 0) {
|
|
37
|
+
const reqSource =
|
|
38
|
+
config.commands?.pr?.requirementSource || config.requirementSource || 'github';
|
|
39
|
+
for (const reqArg of requirementArgs) {
|
|
40
|
+
const req = await getRequirementsFromSource(reqSource, reqArg, config);
|
|
41
|
+
if (req) requirements += req + '\n';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Build preamble from system messages
|
|
46
|
+
const preamble = buildSystemMessages(config, 'pr');
|
|
47
|
+
const preambleText = preamble
|
|
48
|
+
.map((m) => (typeof m.content === 'string' ? m.content : ''))
|
|
49
|
+
.join('\n');
|
|
50
|
+
|
|
51
|
+
// Combine requirements and content for the review
|
|
52
|
+
const diffWithReqs = requirements
|
|
53
|
+
? `Requirements:\n${requirements}\nDiff:\n${content}`
|
|
54
|
+
: content;
|
|
55
|
+
|
|
56
|
+
await review('pr-review', preambleText, diffWithReqs, config, 'pr');
|
|
57
|
+
} catch (error) {
|
|
58
|
+
displayError(error instanceof Error ? error.message : String(error));
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
main();
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { GthConfig } from '@gaunt-sloth/core/config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Requirements sources. Expected to be in `.sources/` dir.
|
|
4
|
+
* Aliases are mapped to actual sources in this file
|
|
5
|
+
*/
|
|
6
|
+
export declare const REQUIREMENTS_PROVIDERS: {
|
|
7
|
+
readonly 'jira-legacy': "jiraIssueLegacySource.js";
|
|
8
|
+
readonly jira: "jiraIssueSource.js";
|
|
9
|
+
readonly github: "ghIssueSource.js";
|
|
10
|
+
readonly text: "textSource.js";
|
|
11
|
+
readonly file: "fileSource.js";
|
|
12
|
+
};
|
|
13
|
+
export type RequirementsProviderType = keyof typeof REQUIREMENTS_PROVIDERS;
|
|
14
|
+
/**
|
|
15
|
+
* Content sources. Expected to be in `.sources/` dir.
|
|
16
|
+
* Aliases are mapped to actual sources in this file
|
|
17
|
+
*/
|
|
18
|
+
export declare const CONTENT_PROVIDERS: {
|
|
19
|
+
readonly github: "ghPrDiffSource.js";
|
|
20
|
+
readonly text: "textSource.js";
|
|
21
|
+
readonly file: "fileSource.js";
|
|
22
|
+
};
|
|
23
|
+
export type ContentProviderType = keyof typeof CONTENT_PROVIDERS;
|
|
24
|
+
export declare function getRequirementsFromSource(requirementsProvider: RequirementsProviderType | undefined, requirementsId: string | undefined, config: GthConfig): Promise<string>;
|
|
25
|
+
export declare function getContentFromSource(contentProvider: ContentProviderType | undefined, contentId: string | undefined, config: GthConfig): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated Use getRequirementsFromSource instead
|
|
28
|
+
*/
|
|
29
|
+
export declare const getRequirementsFromProvider: typeof getRequirementsFromSource;
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated Use getContentFromSource instead
|
|
32
|
+
*/
|
|
33
|
+
export declare const getContentFromProvider: typeof getContentFromSource;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { displayError } from '@gaunt-sloth/core/utils/consoleUtils.js';
|
|
2
|
+
import { wrapContent } from '@gaunt-sloth/core/utils/llmUtils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Requirements sources. Expected to be in `.sources/` dir.
|
|
5
|
+
* Aliases are mapped to actual sources in this file
|
|
6
|
+
*/
|
|
7
|
+
export const REQUIREMENTS_PROVIDERS = {
|
|
8
|
+
'jira-legacy': 'jiraIssueLegacySource.js',
|
|
9
|
+
jira: 'jiraIssueSource.js',
|
|
10
|
+
github: 'ghIssueSource.js',
|
|
11
|
+
text: 'textSource.js',
|
|
12
|
+
file: 'fileSource.js',
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Content sources. Expected to be in `.sources/` dir.
|
|
16
|
+
* Aliases are mapped to actual sources in this file
|
|
17
|
+
*/
|
|
18
|
+
export const CONTENT_PROVIDERS = {
|
|
19
|
+
github: 'ghPrDiffSource.js',
|
|
20
|
+
text: 'textSource.js',
|
|
21
|
+
file: 'fileSource.js',
|
|
22
|
+
};
|
|
23
|
+
export async function getRequirementsFromSource(requirementsProvider, requirementsId, config) {
|
|
24
|
+
const requirements = await getFromProvider(requirementsProvider, requirementsId, (config?.requirementsProviderConfig ?? {})[requirementsProvider], REQUIREMENTS_PROVIDERS);
|
|
25
|
+
return wrapContent(requirements, requirementsProvider, 'requirements');
|
|
26
|
+
}
|
|
27
|
+
export async function getContentFromSource(contentProvider, contentId, config) {
|
|
28
|
+
const content = await getFromProvider(contentProvider, contentId, (config?.contentProviderConfig ?? {})[contentProvider], CONTENT_PROVIDERS);
|
|
29
|
+
return wrapContent(content, contentProvider, contentProvider === 'github' ? 'GitHub diff' : 'content');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* @deprecated Use getRequirementsFromSource instead
|
|
33
|
+
*/
|
|
34
|
+
export const getRequirementsFromProvider = getRequirementsFromSource;
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated Use getContentFromSource instead
|
|
37
|
+
*/
|
|
38
|
+
export const getContentFromProvider = getContentFromSource;
|
|
39
|
+
async function getFromProvider(provider, id,
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
|
+
config, legitPredefinedProviders) {
|
|
42
|
+
if (typeof provider === 'string') {
|
|
43
|
+
// Use one of the predefined providers
|
|
44
|
+
if (legitPredefinedProviders[provider]) {
|
|
45
|
+
const providerPath = `#src/sources/${legitPredefinedProviders[provider]}`;
|
|
46
|
+
const { get } = await import(providerPath);
|
|
47
|
+
return await get(config, id);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
displayError(`Unknown provider: ${provider}. Continuing without it.`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else if (typeof provider === 'function') {
|
|
54
|
+
// Type assertion to handle function call
|
|
55
|
+
return await provider(id);
|
|
56
|
+
}
|
|
57
|
+
return '';
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=commandUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandUtils.js","sourceRoot":"","sources":["../../src/commands/commandUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAEvE,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAElE;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,aAAa,EAAE,0BAA0B;IACzC,IAAI,EAAE,oBAAoB;IAC1B,MAAM,EAAE,kBAAkB;IAC1B,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,eAAe;CACb,CAAC;AAIX;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,MAAM,EAAE,mBAAmB;IAC3B,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,eAAe;CACb,CAAC;AAIX,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,oBAA0D,EAC1D,cAAkC,EAClC,MAAiB;IAEjB,MAAM,YAAY,GAAG,MAAM,eAAe,CACxC,oBAAoB,EACpB,cAAc,EACd,CAAC,MAAM,EAAE,0BAA0B,IAAI,EAAE,CAAC,CAAC,oBAA8B,CAAC,EAC1E,sBAAsB,CACvB,CAAC;IACF,OAAO,WAAW,CAAC,YAAY,EAAE,oBAAoB,EAAE,cAAc,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,eAAgD,EAChD,SAA6B,EAC7B,MAAiB;IAEjB,MAAM,OAAO,GAAG,MAAM,eAAe,CACnC,eAAe,EACf,SAAS,EACT,CAAC,MAAM,EAAE,qBAAqB,IAAI,EAAE,CAAC,CAAC,eAAyB,CAAC,EAChE,iBAAiB,CAClB,CAAC;IACF,OAAO,WAAW,CAChB,OAAO,EACP,eAAe,EACf,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CACzD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,yBAAyB,CAAC;AAErE;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;AAE3D,KAAK,UAAU,eAAe,CAC5B,QAAoE,EACpE,EAAsB;AACtB,8DAA8D;AAC9D,MAAW,EACX,wBAAkF;IAElF,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,sCAAsC;QACtC,IAAI,wBAAwB,CAAC,QAAiD,CAAC,EAAE,CAAC;YAChF,MAAM,YAAY,GAAG,gBAAgB,wBAAwB,CAAC,QAAiD,CAAC,EAAE,CAAC;YACnH,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;YAC3C,OAAO,MAAM,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,qBAAqB,QAAQ,0BAA0B,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC1C,yCAAyC;QACzC,OAAO,MAAO,QAAwD,CAAC,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@gaunt-sloth/core/config.js';
|
package/dist/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@gaunt-sloth/core/constants.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { GthAgentRunner } from '@gaunt-sloth/core/core/GthAgentRunner.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GthAgentRunner.js","sourceRoot":"","sources":["../../src/core/GthAgentRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@gaunt-sloth/core/core/types.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { JiraConfig } from '#src/sources/types.js';
|
|
2
|
+
export interface ResolvedJiraCredentials {
|
|
3
|
+
cloudId: string;
|
|
4
|
+
username?: string;
|
|
5
|
+
token?: string;
|
|
6
|
+
fullBase64Token?: string;
|
|
7
|
+
displayUrl?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function getJiraCredentials(config: Partial<JiraConfig> | null): ResolvedJiraCredentials;
|
|
10
|
+
export declare function getJiraHeaders(config: ResolvedJiraCredentials): Record<string, string>;
|
|
11
|
+
export declare function jiraRequest<T>(config: ResolvedJiraCredentials, endpoint: string, options?: RequestInit, showProgress?: boolean): Promise<T>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { env } from '@gaunt-sloth/core/utils/systemUtils.js';
|
|
2
|
+
import { ProgressIndicator } from '@gaunt-sloth/core/utils/ProgressIndicator.js';
|
|
3
|
+
export function getJiraCredentials(config) {
|
|
4
|
+
if (!config) {
|
|
5
|
+
throw new Error('No Jira config provided');
|
|
6
|
+
}
|
|
7
|
+
const cloudId = env.JIRA_CLOUD_ID || config.cloudId;
|
|
8
|
+
if (!cloudId) {
|
|
9
|
+
throw new Error('Missing JIRA Cloud ID. The Cloud ID can be defined as JIRA_CLOUD_ID environment variable or as "cloudId" in config.');
|
|
10
|
+
}
|
|
11
|
+
const fullBase64Token = env.JIRA_FULL_BASE64_TOKEN || config.fullBase64Token;
|
|
12
|
+
if (fullBase64Token) {
|
|
13
|
+
return {
|
|
14
|
+
cloudId,
|
|
15
|
+
fullBase64Token,
|
|
16
|
+
displayUrl: config.displayUrl,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const username = env.JIRA_USERNAME || config.username;
|
|
20
|
+
if (!username) {
|
|
21
|
+
throw new Error('Missing JIRA username. The username can be defined as JIRA_USERNAME environment variable or as "username" in config.');
|
|
22
|
+
}
|
|
23
|
+
const token = env.JIRA_API_PAT_TOKEN || config.token;
|
|
24
|
+
if (!token) {
|
|
25
|
+
throw new Error('Missing JIRA PAT token. The token can be defined as JIRA_API_PAT_TOKEN environment variable or as "token" in config.');
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
cloudId,
|
|
29
|
+
username,
|
|
30
|
+
token,
|
|
31
|
+
displayUrl: config.displayUrl,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function getJiraHeaders(config) {
|
|
35
|
+
const authHeader = config.fullBase64Token
|
|
36
|
+
? `Basic ${config.fullBase64Token}`
|
|
37
|
+
: `Basic ${Buffer.from(`${config.username}:${config.token}`).toString('base64')}`;
|
|
38
|
+
return {
|
|
39
|
+
Authorization: authHeader,
|
|
40
|
+
Accept: 'application/json; charset=utf-8',
|
|
41
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
42
|
+
'Content-Type': 'application/json',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export async function jiraRequest(config, endpoint, options = {}, showProgress = true) {
|
|
46
|
+
const apiUrl = `https://api.atlassian.com/ex/jira/${config.cloudId}${endpoint}`;
|
|
47
|
+
const headers = getJiraHeaders(config);
|
|
48
|
+
let progressIndicator;
|
|
49
|
+
if (showProgress) {
|
|
50
|
+
progressIndicator = new ProgressIndicator(`${options.method || 'GET'} ${apiUrl.replace(/^https?:\/\//, '')}`);
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const response = await fetch(apiUrl, {
|
|
54
|
+
...options,
|
|
55
|
+
headers: {
|
|
56
|
+
...headers,
|
|
57
|
+
...options.headers,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
if (progressIndicator) {
|
|
61
|
+
progressIndicator.stop();
|
|
62
|
+
}
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
let errorMessage = `Failed to fetch from Jira: ${response.statusText}`;
|
|
65
|
+
try {
|
|
66
|
+
const errorData = await response.json();
|
|
67
|
+
errorMessage += ` - ${JSON.stringify(errorData)}`;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// If we can't parse JSON error, use the basic message
|
|
71
|
+
}
|
|
72
|
+
throw new Error(errorMessage);
|
|
73
|
+
}
|
|
74
|
+
return response.json();
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (progressIndicator) {
|
|
78
|
+
progressIndicator.stop();
|
|
79
|
+
}
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=jiraClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jiraClient.js","sourceRoot":"","sources":["../../../src/helpers/jira/jiraClient.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yCAAyC,CAAC;AACxD,cAAc,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* Middleware responsible for generating review ratings after the agent finishes.
|
|
4
|
+
*
|
|
5
|
+
* The middleware runs an additional model call that summarizes the review outcome
|
|
6
|
+
* and stores the structured result inside the global artifact store.
|
|
7
|
+
*/
|
|
8
|
+
import { type AgentMiddleware } from 'langchain';
|
|
9
|
+
import * as z from 'zod';
|
|
10
|
+
import type { GthConfig, RatingConfig } from '@gaunt-sloth/core/config.js';
|
|
11
|
+
/**
|
|
12
|
+
* Schema describing the result of the review rating step.
|
|
13
|
+
*/
|
|
14
|
+
export declare const RateSchema: z.ZodObject<{
|
|
15
|
+
rate: z.ZodNumber;
|
|
16
|
+
comment: z.ZodString;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
/**
|
|
19
|
+
* Type representing a review rating response.
|
|
20
|
+
*/
|
|
21
|
+
export type RateResponse = z.infer<typeof RateSchema>;
|
|
22
|
+
export interface ReviewRatingArtifact extends RateResponse {
|
|
23
|
+
passThreshold: number;
|
|
24
|
+
minRating: number;
|
|
25
|
+
maxRating: number;
|
|
26
|
+
}
|
|
27
|
+
export declare const REVIEW_RATE_ARTIFACT_KEY = "gsloth.review.rate";
|
|
28
|
+
interface NormalizedRatingConfig {
|
|
29
|
+
minRating: number;
|
|
30
|
+
maxRating: number;
|
|
31
|
+
passThreshold: number;
|
|
32
|
+
}
|
|
33
|
+
export type ReviewRateMiddlewareSettings = RatingConfig & {
|
|
34
|
+
name?: 'review-rate';
|
|
35
|
+
};
|
|
36
|
+
export declare function normalizeRatingConfig(config: RatingConfig | undefined): NormalizedRatingConfig;
|
|
37
|
+
export declare function createReviewRateMiddleware(settings: ReviewRateMiddlewareSettings, gthConfig: GthConfig): Promise<AgentMiddleware>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* Middleware responsible for generating review ratings after the agent finishes.
|
|
4
|
+
*
|
|
5
|
+
* The middleware runs an additional model call that summarizes the review outcome
|
|
6
|
+
* and stores the structured result inside the global artifact store.
|
|
7
|
+
*/
|
|
8
|
+
import { HumanMessage } from '@langchain/core/messages';
|
|
9
|
+
import { tool } from '@langchain/core/tools';
|
|
10
|
+
import { createAgent, createMiddleware } from 'langchain';
|
|
11
|
+
import * as z from 'zod';
|
|
12
|
+
import { setArtifact, deleteArtifact } from '@gaunt-sloth/core/state/artifactStore.js';
|
|
13
|
+
import { debugLog, debugLogError } from '@gaunt-sloth/core/utils/debugUtils.js';
|
|
14
|
+
import { getNewRunnableConfig } from '@gaunt-sloth/core/utils/llmUtils.js';
|
|
15
|
+
/**
|
|
16
|
+
* Schema describing the result of the review rating step.
|
|
17
|
+
*/
|
|
18
|
+
export const RateSchema = z.object({
|
|
19
|
+
rate: z.number().min(0).max(10).describe('Review rating from 0 to 10'),
|
|
20
|
+
comment: z.string().describe('Comment explaining the rating'),
|
|
21
|
+
});
|
|
22
|
+
export const REVIEW_RATE_ARTIFACT_KEY = 'gsloth.review.rate';
|
|
23
|
+
const DEFAULT_MIN_RATING = 0;
|
|
24
|
+
const DEFAULT_MAX_RATING = 10;
|
|
25
|
+
const DEFAULT_PASS_THRESHOLD = 6;
|
|
26
|
+
export function normalizeRatingConfig(config) {
|
|
27
|
+
const min = config?.minRating ?? DEFAULT_MIN_RATING;
|
|
28
|
+
const max = config?.maxRating ?? DEFAULT_MAX_RATING;
|
|
29
|
+
const [minRating, maxRating] = min <= max ? [min, max] : [max, min];
|
|
30
|
+
const threshold = config?.passThreshold ?? DEFAULT_PASS_THRESHOLD;
|
|
31
|
+
return {
|
|
32
|
+
minRating,
|
|
33
|
+
maxRating,
|
|
34
|
+
passThreshold: clamp(threshold, minRating, maxRating),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const REVIEW_RATE_TOOL_NAME = 'gth_review_rate';
|
|
38
|
+
export function createReviewRateMiddleware(settings, gthConfig) {
|
|
39
|
+
const normalizedConfig = normalizeRatingConfig(settings);
|
|
40
|
+
const rateTool = tool((input) => {
|
|
41
|
+
const artifact = {
|
|
42
|
+
...input,
|
|
43
|
+
...normalizedConfig,
|
|
44
|
+
};
|
|
45
|
+
setArtifact(REVIEW_RATE_ARTIFACT_KEY, artifact);
|
|
46
|
+
return `Stored rating ${input.rate}/${normalizedConfig.maxRating}`;
|
|
47
|
+
}, {
|
|
48
|
+
name: REVIEW_RATE_TOOL_NAME,
|
|
49
|
+
description: 'Stores the final review rating and summary comment.',
|
|
50
|
+
schema: RateSchema,
|
|
51
|
+
});
|
|
52
|
+
const ratingAgent = createAgent({
|
|
53
|
+
model: gthConfig.llm,
|
|
54
|
+
tools: [rateTool],
|
|
55
|
+
});
|
|
56
|
+
return Promise.resolve(createMiddleware({
|
|
57
|
+
name: 'review-rate',
|
|
58
|
+
afterAgent: async (state) => {
|
|
59
|
+
if (!Array.isArray(state.messages) || state.messages.length === 0) {
|
|
60
|
+
return state;
|
|
61
|
+
}
|
|
62
|
+
deleteArtifact(REVIEW_RATE_ARTIFACT_KEY);
|
|
63
|
+
const ratingPrompt = buildRatingInstructions(normalizedConfig);
|
|
64
|
+
debugLog('ReviewRateMiddleware: requesting rating evaluation');
|
|
65
|
+
try {
|
|
66
|
+
const ratingMessages = [...state.messages, new HumanMessage(ratingPrompt)];
|
|
67
|
+
await ratingAgent.invoke({
|
|
68
|
+
messages: ratingMessages,
|
|
69
|
+
}, getNewRunnableConfig());
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
debugLogError('ReviewRateMiddleware.invoke', error);
|
|
73
|
+
}
|
|
74
|
+
return state;
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
function buildRatingInstructions(config) {
|
|
79
|
+
const formattedThreshold = formatScore(config.passThreshold);
|
|
80
|
+
const formattedMax = formatScore(config.maxRating);
|
|
81
|
+
const formattedMin = formatScore(config.minRating);
|
|
82
|
+
const middle = formatScore((config.passThreshold + config.maxRating) / 2);
|
|
83
|
+
return [
|
|
84
|
+
'A reviewer just finished assessing a code change.',
|
|
85
|
+
'Your job is to inspect the entire conversation above, focus on the code being discussed (not the review quality),',
|
|
86
|
+
'and call the ' + REVIEW_RATE_TOOL_NAME + ' tool exactly once.',
|
|
87
|
+
`Assign a score between ${formattedMin}-${formattedMax} that reflects the code quality only.`,
|
|
88
|
+
`Pass threshold is ${formattedThreshold}, everything below will be considered a fail.`,
|
|
89
|
+
'',
|
|
90
|
+
'Additional guidelines:',
|
|
91
|
+
`- Never give ${formattedThreshold}/${formattedMax} or more to code which would explode with syntax error.`,
|
|
92
|
+
`- Rate excellent code as ${formattedMax}/${formattedMax}`,
|
|
93
|
+
`- Rate code needing improvements as ${middle}/${formattedMax}`,
|
|
94
|
+
'- Use the comment field of the tool call for a concise summary referencing the code state.',
|
|
95
|
+
].join('\n');
|
|
96
|
+
}
|
|
97
|
+
function clamp(value, min, max) {
|
|
98
|
+
return Math.min(Math.max(value, min), max);
|
|
99
|
+
}
|
|
100
|
+
function formatScore(value) {
|
|
101
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(1);
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=reviewRateMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewRateMiddleware.js","sourceRoot":"","sources":["../../src/middleware/reviewRateMiddleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { GthConfig } from '@gaunt-sloth/core/config.js';
|
|
2
|
+
import type { AgentResolvers } from '@gaunt-sloth/core/core/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Ask a question and get an answer from the LLM
|
|
5
|
+
* @param source - The source of the question (used for file naming)
|
|
6
|
+
* @param preamble - The preamble to send to the LLM
|
|
7
|
+
* @param content - The content of the question
|
|
8
|
+
*/
|
|
9
|
+
export declare function askQuestion(source: string, preamble: string, content: string, config: GthConfig, resolvers?: AgentResolvers): Promise<void>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { defaultStatusCallback, display, displayError, displaySuccess, flushSessionLog, initSessionLogging, stopSessionLogging, } from '@gaunt-sloth/core/utils/consoleUtils.js';
|
|
2
|
+
import { getCommandOutputFilePath } from '#src/utils/fileUtils.js';
|
|
3
|
+
import { GthAgentRunner } from '@gaunt-sloth/core/core/GthAgentRunner.js';
|
|
4
|
+
import { MemorySaver } from '@langchain/langgraph';
|
|
5
|
+
import { HumanMessage, SystemMessage } from '@langchain/core/messages';
|
|
6
|
+
import { ProgressIndicator } from '@gaunt-sloth/core/utils/ProgressIndicator.js';
|
|
7
|
+
/**
|
|
8
|
+
* Ask a question and get an answer from the LLM
|
|
9
|
+
* @param source - The source of the question (used for file naming)
|
|
10
|
+
* @param preamble - The preamble to send to the LLM
|
|
11
|
+
* @param content - The content of the question
|
|
12
|
+
*/
|
|
13
|
+
export async function askQuestion(source, preamble, content, config, resolvers) {
|
|
14
|
+
const progressIndicator = config.streamOutput ? undefined : new ProgressIndicator('Thinking.');
|
|
15
|
+
const messages = [new SystemMessage(preamble), new HumanMessage(content)];
|
|
16
|
+
// Resolve output path and initialize session logging if enabled
|
|
17
|
+
const filePath = getCommandOutputFilePath(config, source);
|
|
18
|
+
if (filePath) {
|
|
19
|
+
initSessionLogging(filePath, config.streamSessionInferenceLog);
|
|
20
|
+
}
|
|
21
|
+
// Run via Agent Runner (consistent with interactive session)
|
|
22
|
+
const runner = new GthAgentRunner(defaultStatusCallback, resolvers);
|
|
23
|
+
try {
|
|
24
|
+
await runner.init('ask', config, new MemorySaver());
|
|
25
|
+
await runner.processMessages(messages);
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
displayError(`Failed to get answer: ${err instanceof Error ? err.message : String(err)}`);
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
await runner.cleanup();
|
|
32
|
+
}
|
|
33
|
+
progressIndicator?.stop();
|
|
34
|
+
if (config.writeOutputToFile === false) {
|
|
35
|
+
display('\n'); // something going on in some terminals, they swallow last line of output
|
|
36
|
+
}
|
|
37
|
+
if (filePath) {
|
|
38
|
+
try {
|
|
39
|
+
flushSessionLog();
|
|
40
|
+
stopSessionLogging();
|
|
41
|
+
displaySuccess(`\n\nThis report can be found in ${filePath}`);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
displayError(`Failed to write answer to file: ${filePath}`);
|
|
45
|
+
displayError(error instanceof Error ? error.message : String(error));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=questionAnsweringModule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questionAnsweringModule.js","sourceRoot":"","sources":["../../src/modules/questionAnsweringModule.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,OAAO,EACP,YAAY,EACZ,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AAGjF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,QAAgB,EAChB,OAAe,EACf,MAAiB,EACjB,SAA0B;IAE1B,MAAM,iBAAiB,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC/F,MAAM,QAAQ,GAAG,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;IAE1E,gEAAgE;IAChE,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,IAAI,QAAQ,EAAE,CAAC;QACb,kBAAkB,CAAC,QAAQ,EAAE,MAAM,CAAC,yBAAyB,CAAC,CAAC;IACjE,CAAC;IAED,6DAA6D;IAC7D,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,qBAAqB,EAAE,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC,CAAC;QACpD,MAAM,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,YAAY,CAAC,yBAAyB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAED,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAE1B,IAAI,MAAM,CAAC,iBAAiB,KAAK,KAAK,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,yEAAyE;IAC1F,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC;YACH,eAAe,EAAE,CAAC;YAClB,kBAAkB,EAAE,CAAC;YACrB,cAAc,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;YAC5D,YAAY,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { GthConfig } from '@gaunt-sloth/core/config.js';
|
|
2
|
+
import type { AgentResolvers } from '@gaunt-sloth/core/core/types.js';
|
|
3
|
+
export declare function review(source: string, preamble: string, diff: string, config: GthConfig, command?: 'pr' | 'review', resolvers?: AgentResolvers): Promise<void>;
|