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
package/src/utils.ts
ADDED
@@ -0,0 +1,232 @@
|
|
1
|
+
import { display, displayError, displaySuccess, displayWarning } from '#src/consoleUtils.js';
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
3
|
+
import { SlothConfig } from '#src/config.js';
|
4
|
+
import { resolve } from 'node:path';
|
5
|
+
import { spawn } from 'node:child_process';
|
6
|
+
import { getCurrentDir, getInstallDir, stdout } from '#src/systemUtils.js';
|
7
|
+
import url from 'node:url';
|
8
|
+
|
9
|
+
export function toFileSafeString(string: string): string {
|
10
|
+
return string.replace(/[^A-Za-z0-9]/g, '-');
|
11
|
+
}
|
12
|
+
|
13
|
+
export function fileSafeLocalDate(): string {
|
14
|
+
const date = new Date();
|
15
|
+
const offsetMs = date.getTimezoneOffset() * 60 * 1000;
|
16
|
+
const msLocal = date.getTime() - offsetMs;
|
17
|
+
const dateLocal = new Date(msLocal);
|
18
|
+
const iso = dateLocal.toISOString();
|
19
|
+
const isoLocal = iso.slice(0, 19);
|
20
|
+
return toFileSafeString(isoLocal);
|
21
|
+
}
|
22
|
+
|
23
|
+
export function readFileFromCurrentDir(fileName: string): string {
|
24
|
+
const currentDir = getCurrentDir();
|
25
|
+
const filePath = resolve(currentDir, fileName);
|
26
|
+
display(`Reading file ${filePath}...`);
|
27
|
+
return readFileSyncWithMessages(filePath);
|
28
|
+
}
|
29
|
+
|
30
|
+
export function readFileFromCurrentOrInstallDir(filePath: string, silentCurrent?: boolean): string {
|
31
|
+
const currentDir = getCurrentDir();
|
32
|
+
const currentFilePath = resolve(currentDir, filePath);
|
33
|
+
if (!silentCurrent) {
|
34
|
+
display(`Reading file ${currentFilePath}...`);
|
35
|
+
}
|
36
|
+
|
37
|
+
try {
|
38
|
+
return readFileSync(currentFilePath, { encoding: 'utf8' });
|
39
|
+
} catch (_error) {
|
40
|
+
if (!silentCurrent) {
|
41
|
+
display(`The ${currentFilePath} not found or can\'t be read, trying install directory...`);
|
42
|
+
}
|
43
|
+
const installDir = getInstallDir();
|
44
|
+
const installFilePath = resolve(installDir, filePath);
|
45
|
+
try {
|
46
|
+
return readFileSync(installFilePath, { encoding: 'utf8' });
|
47
|
+
} catch (readFromInstallDirError) {
|
48
|
+
displayError(`The ${installFilePath} not found or can\'t be read.`);
|
49
|
+
throw readFromInstallDirError;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
export function writeFileIfNotExistsWithMessages(filePath: string, content: string): void {
|
55
|
+
display(`checking ${filePath} existence`);
|
56
|
+
if (!existsSync(filePath)) {
|
57
|
+
writeFileSync(filePath, content);
|
58
|
+
displaySuccess(`Created ${filePath}`);
|
59
|
+
} else {
|
60
|
+
displayWarning(`${filePath} already exists`);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
export function readFileSyncWithMessages(
|
65
|
+
filePath: string,
|
66
|
+
errorMessageIn?: string,
|
67
|
+
noFileMessage?: string
|
68
|
+
): string {
|
69
|
+
const errorMessage = errorMessageIn ?? 'Error reading file at: ';
|
70
|
+
try {
|
71
|
+
return readFileSync(filePath, { encoding: 'utf8' });
|
72
|
+
} catch (error) {
|
73
|
+
displayError(errorMessage + filePath);
|
74
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
75
|
+
displayWarning(noFileMessage ?? 'Please ensure the file exists.');
|
76
|
+
} else {
|
77
|
+
displayError((error as Error).message);
|
78
|
+
}
|
79
|
+
throw error;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
interface SpawnOutput {
|
84
|
+
stdout: string;
|
85
|
+
stderr: string;
|
86
|
+
}
|
87
|
+
|
88
|
+
export async function spawnCommand(
|
89
|
+
command: string,
|
90
|
+
args: string[],
|
91
|
+
progressMessage: string,
|
92
|
+
successMessage: string
|
93
|
+
): Promise<string> {
|
94
|
+
return new Promise((resolve, reject) => {
|
95
|
+
const progressIndicator = new ProgressIndicator(progressMessage, true);
|
96
|
+
const out: SpawnOutput = { stdout: '', stderr: '' };
|
97
|
+
const spawned = spawn(command, args);
|
98
|
+
|
99
|
+
spawned.stdout.on('data', async (stdoutChunk) => {
|
100
|
+
progressIndicator.indicate();
|
101
|
+
out.stdout += stdoutChunk.toString();
|
102
|
+
});
|
103
|
+
|
104
|
+
spawned.stderr.on('data', (err) => {
|
105
|
+
progressIndicator.indicate();
|
106
|
+
out.stderr += err.toString();
|
107
|
+
});
|
108
|
+
|
109
|
+
spawned.on('error', (err) => {
|
110
|
+
reject(err.toString());
|
111
|
+
});
|
112
|
+
|
113
|
+
spawned.on('close', (code) => {
|
114
|
+
if (code === 0) {
|
115
|
+
display(successMessage);
|
116
|
+
resolve(out.stdout);
|
117
|
+
} else {
|
118
|
+
displayError(`Failed to spawn command with code ${code}`);
|
119
|
+
reject(out.stdout + ' ' + out.stderr);
|
120
|
+
}
|
121
|
+
});
|
122
|
+
});
|
123
|
+
}
|
124
|
+
|
125
|
+
export function getSlothVersion(): string {
|
126
|
+
// TODO figure out if this can be injected with TS
|
127
|
+
const installDir = getInstallDir();
|
128
|
+
const jsonPath = resolve(installDir, 'package.json');
|
129
|
+
const projectJson = readFileSync(jsonPath, { encoding: 'utf8' });
|
130
|
+
return JSON.parse(projectJson).version;
|
131
|
+
}
|
132
|
+
|
133
|
+
export class ProgressIndicator {
|
134
|
+
private interval: number | undefined = undefined;
|
135
|
+
|
136
|
+
constructor(initialMessage: string, manual?: boolean) {
|
137
|
+
stdout.write(initialMessage);
|
138
|
+
if (!manual) {
|
139
|
+
this.interval = setInterval(this.indicateInner, 1000) as unknown as number;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
private indicateInner(): void {
|
144
|
+
stdout.write('.');
|
145
|
+
}
|
146
|
+
|
147
|
+
indicate(): void {
|
148
|
+
if (this.interval) {
|
149
|
+
throw new Error('ProgressIndicator.indicate only to be called in manual mode');
|
150
|
+
}
|
151
|
+
this.indicateInner();
|
152
|
+
}
|
153
|
+
|
154
|
+
stop(): void {
|
155
|
+
if (this.interval) {
|
156
|
+
clearInterval(this.interval);
|
157
|
+
}
|
158
|
+
stdout.write('\n');
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
interface LLMOutput {
|
163
|
+
messages: Array<{
|
164
|
+
content: string;
|
165
|
+
}>;
|
166
|
+
}
|
167
|
+
|
168
|
+
/**
|
169
|
+
* Extracts the content of the last message from an LLM response
|
170
|
+
* @param output - The output from the LLM containing messages
|
171
|
+
* @returns The content of the last message
|
172
|
+
*/
|
173
|
+
export function extractLastMessageContent(output: LLMOutput): string {
|
174
|
+
if (!output || !output.messages || !output.messages.length) {
|
175
|
+
return '';
|
176
|
+
}
|
177
|
+
return output.messages[output.messages.length - 1].content;
|
178
|
+
}
|
179
|
+
|
180
|
+
/**
|
181
|
+
* Dynamically imports a module from a file path from the outside of the installation dir
|
182
|
+
* @param filePath - The path to the file to import
|
183
|
+
* @returns A promise that resolves to the imported module
|
184
|
+
*/
|
185
|
+
export function importExternalFile(
|
186
|
+
filePath: string
|
187
|
+
): Promise<{ configure: (module: string) => Promise<Partial<SlothConfig>> }> {
|
188
|
+
const configFileUrl = url.pathToFileURL(filePath).toString();
|
189
|
+
return import(configFileUrl);
|
190
|
+
}
|
191
|
+
|
192
|
+
/**
|
193
|
+
* Alias for importExternalFile for backward compatibility with tests
|
194
|
+
* @param filePath - The path to the file to import
|
195
|
+
* @returns A promise that resolves to the imported module
|
196
|
+
*/
|
197
|
+
export const importFromFilePath = importExternalFile;
|
198
|
+
|
199
|
+
/**
|
200
|
+
* Reads multiple files from the current directory and returns their contents
|
201
|
+
* @param fileNames - Array of file names to read
|
202
|
+
* @returns Combined content of all files with proper formatting
|
203
|
+
*/
|
204
|
+
export function readMultipleFilesFromCurrentDir(fileNames: string | string[]): string {
|
205
|
+
if (!Array.isArray(fileNames)) {
|
206
|
+
return readFileFromCurrentDir(fileNames);
|
207
|
+
}
|
208
|
+
|
209
|
+
return fileNames
|
210
|
+
.map((fileName) => {
|
211
|
+
const content = readFileFromCurrentDir(fileName);
|
212
|
+
return `${fileName}:\n\`\`\`\n${content}\n\`\`\``;
|
213
|
+
})
|
214
|
+
.join('\n\n');
|
215
|
+
}
|
216
|
+
|
217
|
+
export async function execAsync(command: string): Promise<string> {
|
218
|
+
const { exec } = await import('node:child_process');
|
219
|
+
return new Promise((resolve, reject) => {
|
220
|
+
exec(command, (error, stdout, stderr) => {
|
221
|
+
if (error) {
|
222
|
+
reject(error);
|
223
|
+
return;
|
224
|
+
}
|
225
|
+
if (stderr) {
|
226
|
+
reject(new Error(stderr));
|
227
|
+
return;
|
228
|
+
}
|
229
|
+
resolve(stdout.trim());
|
230
|
+
});
|
231
|
+
});
|
232
|
+
}
|
package/tsconfig.json
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"target": "ES2022",
|
4
|
+
"module": "NodeNext",
|
5
|
+
"moduleResolution": "NodeNext",
|
6
|
+
"esModuleInterop": true,
|
7
|
+
"strict": true,
|
8
|
+
"skipLibCheck": true,
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
10
|
+
"outDir": "dist",
|
11
|
+
"rootDir": "src",
|
12
|
+
"declaration": true,
|
13
|
+
"sourceMap": true,
|
14
|
+
"typeRoots": ["./node_modules/@types", "./src/types"],
|
15
|
+
"allowJs": true,
|
16
|
+
"checkJs": false,
|
17
|
+
"baseUrl": ".",
|
18
|
+
"paths": {
|
19
|
+
"#src/*": ["./src/*"]
|
20
|
+
}
|
21
|
+
},
|
22
|
+
"include": ["src/**/*"],
|
23
|
+
"exclude": ["node_modules", "dist", "spec"]
|
24
|
+
}
|
package/vitest.config.ts
ADDED
package/.eslint.config.mjs
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
// TODO
|
2
|
-
// // eslint.config.mjs
|
3
|
-
// // Remember to install dependencies:
|
4
|
-
// // npm install --save-dev eslint @eslint/js eslint-plugin-n globals eslint-config-prettier
|
5
|
-
// // yarn add --dev eslint @eslint/js eslint-plugin-n globals eslint-config-prettier
|
6
|
-
// // pnpm add -D eslint @eslint/js eslint-plugin-n globals eslint-config-prettier
|
7
|
-
//
|
8
|
-
// import js from "@eslint/js"; // Provides eslint:recommended and eslint:all
|
9
|
-
// import pluginN from "eslint-plugin-n"; // Successor to eslint-plugin-node
|
10
|
-
// import globals from "globals"; // Provides standard global variables (node, browser, etc.)
|
11
|
-
// import eslintConfigPrettier from "eslint-config-prettier"; // Disables rules that conflict with Prettier
|
12
|
-
//
|
13
|
-
// export default [
|
14
|
-
// // 1. Global Ignores
|
15
|
-
// // Files/directories to ignore globally. You can add more patterns.
|
16
|
-
// {
|
17
|
-
// ignores: [
|
18
|
-
// "node_modules/",
|
19
|
-
// "dist/", // Common build output directory
|
20
|
-
// "build/", // Another common build output directory
|
21
|
-
// ".env",
|
22
|
-
// "*.log",
|
23
|
-
// "coverage/", // Test coverage reports
|
24
|
-
// ],
|
25
|
-
// },
|
26
|
-
//
|
27
|
-
// // 2. ESLint Recommended Rules
|
28
|
-
// // Provides a good baseline set of rules maintained by the ESLint team.
|
29
|
-
// js.configs.recommended,
|
30
|
-
//
|
31
|
-
// // 3. Node.js Specific Rules (using eslint-plugin-n)
|
32
|
-
// // Recommended configuration for Node.js projects.
|
33
|
-
// pluginN.configs['flat/recommended'],
|
34
|
-
//
|
35
|
-
// // 4. Custom Configuration for your JS/MJS files
|
36
|
-
// {
|
37
|
-
// files: ["**/*.{js,mjs}"], // Apply these settings to .js and .mjs files
|
38
|
-
// languageOptions: {
|
39
|
-
// ecmaVersion: "latest", // Use the latest ECMAScript features
|
40
|
-
// sourceType: "module", // Set to "module" for ES Modules (import/export)
|
41
|
-
// globals: {
|
42
|
-
// ...globals.nodeBuiltin, // Includes Node.js built-in globals like 'process', 'Buffer', etc.
|
43
|
-
// // Add other global environments if needed:
|
44
|
-
// // ...globals.browser, // If your code also runs in the browser
|
45
|
-
// // Add any other custom global variables your project uses:
|
46
|
-
// // myCustomGlobal: "readonly",
|
47
|
-
// }
|
48
|
-
// },
|
49
|
-
// rules: {
|
50
|
-
// // Customize or override rules here
|
51
|
-
// "no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }], // Warn about unused vars, except those starting with _
|
52
|
-
// "semi": ["error", "always"], // Enforce semicolons
|
53
|
-
// "quotes": ["warn", "single"], // Prefer single quotes
|
54
|
-
// "indent": ["warn", 2], // Enforce 2-space indentation
|
55
|
-
//
|
56
|
-
// // Node specific rule examples (from eslint-plugin-n) - adjust as needed
|
57
|
-
// "n/no-unpublished-import": ["error", {
|
58
|
-
// "allowModules": [], // Add exceptions for modules used in dev but not in dependencies
|
59
|
-
// }],
|
60
|
-
// "n/no-missing-import": "error", // Ensure imports can be resolved
|
61
|
-
// "n/no-extraneous-import": "error", // Prevent importing devDependencies in production code
|
62
|
-
//
|
63
|
-
// // Add other rules or modify existing ones based on your team's style guide
|
64
|
-
// }
|
65
|
-
// },
|
66
|
-
//
|
67
|
-
// // 5. Prettier Configuration (Optional but Recommended)
|
68
|
-
// // IMPORTANT: This MUST be the LAST configuration object in the array.
|
69
|
-
// // It disables ESLint rules that would conflict with Prettier's formatting.
|
70
|
-
// // Assumes you are using Prettier for code formatting.
|
71
|
-
// eslintConfigPrettier,
|
72
|
-
// ];
|
package/.github/dependabot.yml
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# To get started with Dependabot version updates, you'll need to specify which
|
2
|
-
# package ecosystems to update and where the package manifests are located.
|
3
|
-
# Please see the documentation for all configuration options:
|
4
|
-
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
5
|
-
|
6
|
-
version: 2
|
7
|
-
updates:
|
8
|
-
- package-ecosystem: "npm" # See documentation for possible values
|
9
|
-
directory: "/" # Location of package manifests
|
10
|
-
schedule:
|
11
|
-
interval: "weekly"
|
package/.github/workflows/ci.yml
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
name: Tests and Lint
|
2
|
-
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
branches: [ "main" ]
|
6
|
-
pull_request:
|
7
|
-
branches: [ "main" ]
|
8
|
-
|
9
|
-
jobs:
|
10
|
-
test-and-lint:
|
11
|
-
runs-on: ubuntu-latest
|
12
|
-
|
13
|
-
strategy:
|
14
|
-
matrix:
|
15
|
-
node-version: [22.x]
|
16
|
-
|
17
|
-
steps:
|
18
|
-
- uses: actions/checkout@v4
|
19
|
-
|
20
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
21
|
-
uses: actions/setup-node@v4
|
22
|
-
with:
|
23
|
-
node-version: ${{ matrix.node-version }}
|
24
|
-
cache: 'npm'
|
25
|
-
|
26
|
-
- name: Install dependencies
|
27
|
-
run: npm ci
|
28
|
-
|
29
|
-
- name: Run ESLint
|
30
|
-
run: npm run lint
|
31
|
-
|
32
|
-
- name: Run Tests
|
33
|
-
run: npm test
|
package/spec/.gsloth.config.js
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
export async function configure(importFunction, global) {
|
2
|
-
const test = await importFunction('@langchain/core/utils/testing');
|
3
|
-
return {
|
4
|
-
llm: new test.FakeListChatModel({
|
5
|
-
responses: ["First LLM message", "Second LLM message"],
|
6
|
-
}),
|
7
|
-
requirementsProviderConfig: {
|
8
|
-
'jira-legacy': {
|
9
|
-
username: 'user.name@company.com', // Your Jira username/email
|
10
|
-
token: 'YoUrToKeN', // Replace with your real Jira API token
|
11
|
-
baseUrl: 'https://company.atlassian.net/rest/api/2/issue/' // Your Jira instance base URL
|
12
|
-
}
|
13
|
-
},
|
14
|
-
requirementsProvider: "jira-legacy",
|
15
|
-
contentProvider: "somethingSpecial",
|
16
|
-
contentProviderConfig: {
|
17
|
-
somethingSpecial: {
|
18
|
-
test: 'example'
|
19
|
-
}
|
20
|
-
}
|
21
|
-
};
|
22
|
-
}
|
package/spec/.gsloth.config.json
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"llm": {
|
3
|
-
"type": "fake",
|
4
|
-
"responses": ["First LLM message", "Second LLM message"]
|
5
|
-
},
|
6
|
-
"requirementsProviderConfig": {
|
7
|
-
"jira-legacy": {
|
8
|
-
"username": "user.name@company.com",
|
9
|
-
"token": "YoUrToKeN",
|
10
|
-
"baseUrl": "https://company.atlassian.net/rest/api/2/issue/"
|
11
|
-
}
|
12
|
-
},
|
13
|
-
"requirementsProvider": "file",
|
14
|
-
"contentProvider": "somethingSpecial",
|
15
|
-
"contentProviderConfig": {
|
16
|
-
"somethingSpecial": {
|
17
|
-
"test": "example"
|
18
|
-
}
|
19
|
-
},
|
20
|
-
"commands": {
|
21
|
-
"pr": {
|
22
|
-
"requirementsProvider": "jira-legacy"
|
23
|
-
}
|
24
|
-
}
|
25
|
-
}
|
package/spec/askCommand.spec.js
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
import {Command} from 'commander';
|
2
|
-
import * as td from 'testdouble';
|
3
|
-
|
4
|
-
describe('askCommand', function (){
|
5
|
-
|
6
|
-
beforeEach(async function() {
|
7
|
-
td.reset();
|
8
|
-
this.askQuestion = td.function();
|
9
|
-
this.prompt = await td.replaceEsm("../src/prompt.js");
|
10
|
-
td.when(this.prompt.readInternalPreamble()).thenReturn("INTERNAL PREAMBLE");
|
11
|
-
this.questionAnsweringMock = await td.replaceEsm("../src/modules/questionAnsweringModule.js");
|
12
|
-
await td.replaceEsm("../src/config.js", {
|
13
|
-
SLOTH_INTERNAL_PREAMBLE: '.gsloth.preamble.internal.md',
|
14
|
-
USER_PROJECT_REVIEW_PREAMBLE: '.gsloth.preamble.review.md',
|
15
|
-
slothContext: {
|
16
|
-
config: {},
|
17
|
-
currentDir: '/mock/current/dir'
|
18
|
-
},
|
19
|
-
initConfig: td.function()
|
20
|
-
});
|
21
|
-
const readFileFromCurrentDir = td.function();
|
22
|
-
const readMultipleFilesFromCurrentDir = td.function();
|
23
|
-
const extractLastMessageContent = td.function();
|
24
|
-
const toFileSafeString = td.function();
|
25
|
-
const fileSafeLocalDate = td.function();
|
26
|
-
this.utilsMock = {
|
27
|
-
readFileFromCurrentDir,
|
28
|
-
readMultipleFilesFromCurrentDir,
|
29
|
-
ProgressIndicator: td.constructor(),
|
30
|
-
extractLastMessageContent,
|
31
|
-
toFileSafeString,
|
32
|
-
fileSafeLocalDate
|
33
|
-
};
|
34
|
-
await td.replaceEsm("../src/utils.js", this.utilsMock);
|
35
|
-
td.when(this.utilsMock.readFileFromCurrentDir("test.file")).thenReturn("FILE CONTENT");
|
36
|
-
td.when(this.utilsMock.readMultipleFilesFromCurrentDir(["test.file"])).thenReturn("test.file:\n```\nFILE CONTENT\n```");
|
37
|
-
td.when(this.questionAnsweringMock.askQuestion(
|
38
|
-
'sloth-ASK',
|
39
|
-
td.matchers.anything(),
|
40
|
-
td.matchers.anything())
|
41
|
-
).thenDo(this.askQuestion);
|
42
|
-
});
|
43
|
-
|
44
|
-
it('Should call askQuestion with message', async function() {
|
45
|
-
const { askCommand } = await import("../src/commands/askCommand.js");
|
46
|
-
const program = new Command();
|
47
|
-
await askCommand(program, {});
|
48
|
-
await program.parseAsync(['na', 'na', 'ask', 'test message']);
|
49
|
-
td.verify(this.askQuestion('sloth-ASK', "INTERNAL PREAMBLE", "test message"));
|
50
|
-
});
|
51
|
-
|
52
|
-
it('Should call askQuestion with message and file content', async function() {
|
53
|
-
const { askCommand } = await import("../src/commands/askCommand.js");
|
54
|
-
const program = new Command();
|
55
|
-
await askCommand(program, {});
|
56
|
-
await program.parseAsync(['na', 'na', 'ask', 'test message', '-f', 'test.file']);
|
57
|
-
td.verify(this.askQuestion('sloth-ASK', "INTERNAL PREAMBLE", "test message\ntest.file:\n```\nFILE CONTENT\n```"));
|
58
|
-
});
|
59
|
-
|
60
|
-
it('Should call askQuestion with message and multiple file contents', async function() {
|
61
|
-
const { askCommand } = await import("../src/commands/askCommand.js");
|
62
|
-
const program = new Command();
|
63
|
-
await askCommand(program, {});
|
64
|
-
td.when(this.utilsMock.readMultipleFilesFromCurrentDir(["test.file", "test2.file"]))
|
65
|
-
.thenReturn("test.file:\n```\nFILE CONTENT\n```\n\ntest2.file:\n```\nFILE2 CONTENT\n```");
|
66
|
-
await program.parseAsync(['na', 'na', 'ask', 'test message', '-f', 'test.file', 'test2.file']);
|
67
|
-
td.verify(this.askQuestion('sloth-ASK', "INTERNAL PREAMBLE", "test message\ntest.file:\n```\nFILE CONTENT\n```\n\ntest2.file:\n```\nFILE2 CONTENT\n```"));
|
68
|
-
});
|
69
|
-
|
70
|
-
it('Should display help correctly', async function() {
|
71
|
-
const { askCommand } = await import("../src/commands/askCommand.js");
|
72
|
-
const program = new Command();
|
73
|
-
const testOutput = { text: '' };
|
74
|
-
|
75
|
-
program.configureOutput({
|
76
|
-
writeOut: (str) => testOutput.text += str,
|
77
|
-
writeErr: (str) => testOutput.text += str
|
78
|
-
});
|
79
|
-
|
80
|
-
await askCommand(program, {});
|
81
|
-
|
82
|
-
const commandUnderTest = program.commands.find(c => c.name() == 'ask');
|
83
|
-
|
84
|
-
expect(commandUnderTest).toBeDefined();
|
85
|
-
commandUnderTest.outputHelp();
|
86
|
-
|
87
|
-
// Verify help content
|
88
|
-
expect(testOutput.text).toContain('Ask a question');
|
89
|
-
expect(testOutput.text).toContain('<message>');
|
90
|
-
expect(testOutput.text).toContain('-f, --file');
|
91
|
-
});
|
92
|
-
});
|