gaunt-sloth-assistant 0.3.0 → 0.3.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.
Files changed (40) hide show
  1. package/.gsloth.guidelines.md +112 -102
  2. package/.gsloth.review.md +8 -2
  3. package/dist/commands/askCommand.js +1 -2
  4. package/dist/commands/askCommand.js.map +1 -1
  5. package/dist/commands/reviewCommand.js +2 -4
  6. package/dist/commands/reviewCommand.js.map +1 -1
  7. package/dist/config.js +44 -16
  8. package/dist/config.js.map +1 -1
  9. package/dist/filePathUtils.d.ts +25 -0
  10. package/dist/filePathUtils.js +66 -0
  11. package/dist/filePathUtils.js.map +1 -0
  12. package/dist/modules/questionAnsweringModule.js +4 -4
  13. package/dist/modules/questionAnsweringModule.js.map +1 -1
  14. package/dist/modules/reviewModule.js +5 -4
  15. package/dist/modules/reviewModule.js.map +1 -1
  16. package/dist/prompt.js +5 -2
  17. package/dist/prompt.js.map +1 -1
  18. package/dist/utils.d.ts +10 -0
  19. package/dist/utils.js +29 -8
  20. package/dist/utils.js.map +1 -1
  21. package/docs/CONFIGURATION.md +21 -0
  22. package/docs/RELEASE-HOWTO.md +8 -6
  23. package/package.json +1 -1
  24. package/src/commands/askCommand.ts +1 -2
  25. package/src/commands/reviewCommand.ts +2 -4
  26. package/src/config.ts +47 -19
  27. package/src/filePathUtils.ts +79 -0
  28. package/src/modules/questionAnsweringModule.ts +4 -7
  29. package/src/modules/reviewModule.ts +5 -7
  30. package/src/prompt.ts +5 -2
  31. package/src/utils.ts +33 -8
  32. package/UX-RESEARCH.md +0 -78
  33. package/gth-ASK-2025-05-16T14-11-39.md +0 -3
  34. package/gth-ASK-2025-05-16T14-18-27.md +0 -3
  35. package/gth-ASK-2025-05-16T14-18-56.md +0 -1
  36. package/gth-ASK-2025-05-16T14-41-20.md +0 -3
  37. package/gth-ASK-2025-05-16T14-43-31.md +0 -51
  38. package/gth-ASK-2025-05-16T16-05-52.md +0 -62
  39. package/gth-DIFF-review-2025-05-16T16-07-53.md +0 -56
  40. package/gth-DIFF-review-2025-05-16T16-18-55.md +0 -292
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,+BAA+B,EAC/B,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,UAAU,aAAa;IAC3B,OAAO,+BAA+B,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,kBAA0B;IACvD,IAAI,CAAC;QACH,OAAO,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CACV,mGAAmG,CACpG,CAAC;QACF,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,kBAA0B;IAC/D,OAAO,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,oBAAoB,CAAC,kBAA0B;IACtD,IAAI,CAAC;QACH,OAAO,+BAA+B,CAAC,kBAAkB,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CACV,mGAAmG,CACpG,CAAC;QACF,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAU;IACxC,iEAAiE;IACjE,IAAI,CAAC;QACH,OAAO,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,CAAC;IAC/F,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,YAAY,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,YAAY,CAAC,8BAA8B,EAAE,mCAAmC,CAAC,CAAC;QAClF,IAAI,EAAE,CAAC;QACP,OAAO,EAAE,CAAC,CAAC,gDAAgD;IAC7D,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,+BAA+B,EAC/B,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,MAAM,UAAU,aAAa;IAC3B,OAAO,+BAA+B,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,kBAA0B;IACvD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;QAC7D,OAAO,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CACV,mGAAmG,CACpG,CAAC;QACF,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,kBAA0B;IAC/D,OAAO,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,oBAAoB,CAAC,kBAA0B;IACtD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;QAC7D,OAAO,+BAA+B,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CACV,mGAAmG,CACpG,CAAC;QACF,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAU;IACxC,iEAAiE;IACjE,IAAI,CAAC;QACH,OAAO,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,CAAC;IAC/F,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,YAAY,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,YAAY,CAAC,8BAA8B,EAAE,mCAAmC,CAAC,CAAC;QAClF,IAAI,EAAE,CAAC;QACP,OAAO,EAAE,CAAC,CAAC,gDAAgD;IAC7D,CAAC;AACH,CAAC"}
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,16 @@
1
1
  import { SlothConfig } from '#src/config.js';
2
2
  export declare function toFileSafeString(string: string): string;
3
+ /**
4
+ * Returns a formatted date string in the format YYYY-MM-DD_HH-MM-SS using local time
5
+ * @returns A formatted date string
6
+ */
3
7
  export declare function fileSafeLocalDate(): string;
8
+ /**
9
+ * Generates a standardized filename with the format: gth_YYYY-MM-DD_HH-MM-SS_COMMAND.md
10
+ * @param command - The command that created the file (ASK, REVIEW, PR, etc.)
11
+ * @returns A standardized filename string
12
+ */
13
+ export declare function generateStandardFileName(command: string): string;
4
14
  export declare function readFileFromCurrentDir(fileName: string): string;
5
15
  export declare function readFileFromCurrentOrInstallDir(filePath: string, silentCurrent?: boolean): string;
6
16
  export declare function writeFileIfNotExistsWithMessages(filePath: string, content: string): void;
package/dist/utils.js CHANGED
@@ -1,20 +1,36 @@
1
1
  import { display, displayError, displaySuccess, displayWarning } from '#src/consoleUtils.js';
2
- import { existsSync, readFileSync, writeFileSync } from 'node:fs';
3
- import { resolve } from 'node:path';
2
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
3
+ import { resolve, dirname } from 'node:path';
4
4
  import { spawn } from 'node:child_process';
5
5
  import { getCurrentDir, getInstallDir, stdout } from '#src/systemUtils.js';
6
6
  import url from 'node:url';
7
7
  export function toFileSafeString(string) {
8
8
  return string.replace(/[^A-Za-z0-9]/g, '-');
9
9
  }
10
+ /**
11
+ * Returns a formatted date string in the format YYYY-MM-DD_HH-MM-SS using local time
12
+ * @returns A formatted date string
13
+ */
10
14
  export function fileSafeLocalDate() {
11
15
  const date = new Date();
12
- const offsetMs = date.getTimezoneOffset() * 60 * 1000;
13
- const msLocal = date.getTime() - offsetMs;
14
- const dateLocal = new Date(msLocal);
15
- const iso = dateLocal.toISOString();
16
- const isoLocal = iso.slice(0, 19);
17
- return toFileSafeString(isoLocal);
16
+ // Format: YYYY-MM-DD_HH-MM-SS using local time directly
17
+ const year = date.getFullYear();
18
+ const month = String(date.getMonth() + 1).padStart(2, '0');
19
+ const day = String(date.getDate()).padStart(2, '0');
20
+ const hours = String(date.getHours()).padStart(2, '0');
21
+ const minutes = String(date.getMinutes()).padStart(2, '0');
22
+ const seconds = String(date.getSeconds()).padStart(2, '0');
23
+ return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;
24
+ }
25
+ /**
26
+ * Generates a standardized filename with the format: gth_YYYY-MM-DD_HH-MM-SS_COMMAND.md
27
+ * @param command - The command that created the file (ASK, REVIEW, PR, etc.)
28
+ * @returns A standardized filename string
29
+ */
30
+ export function generateStandardFileName(command) {
31
+ const dateTimeStr = fileSafeLocalDate();
32
+ const commandStr = toFileSafeString(command.toUpperCase());
33
+ return `gth_${dateTimeStr}_${commandStr}.md`;
18
34
  }
19
35
  export function readFileFromCurrentDir(fileName) {
20
36
  const currentDir = getCurrentDir();
@@ -49,6 +65,11 @@ export function readFileFromCurrentOrInstallDir(filePath, silentCurrent) {
49
65
  export function writeFileIfNotExistsWithMessages(filePath, content) {
50
66
  display(`checking ${filePath} existence`);
51
67
  if (!existsSync(filePath)) {
68
+ // Create parent directories if they don't exist
69
+ const parentDir = dirname(filePath);
70
+ if (!existsSync(parentDir)) {
71
+ mkdirSync(parentDir, { recursive: true });
72
+ }
52
73
  writeFileSync(filePath, content);
53
74
  displaySuccess(`Created ${filePath}`);
54
75
  }
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,27 @@ Your project should have the following files in order for gsloth to function:
14
14
  > Gaunt Sloth currently only functions from the directory which has one of the configuration files and `.gsloth.guidelines.md`.
15
15
  > Global configuration to invoke gsloth anywhere is in [ROADMAP](../ROADMAP.md).
16
16
 
17
+ ## Using .gsloth Directory
18
+
19
+ For a tidier project structure, you can create a `.gsloth` directory in your project root. When this directory exists, gsloth will:
20
+
21
+ 1. Write all output files (like responses from commands) to the `.gsloth` directory instead of the project root
22
+ 2. Look for configuration files in `.gsloth/.gsloth-settings/` subdirectory
23
+
24
+ Example directory structure when using the `.gsloth` directory:
25
+
26
+ ```
27
+ .gsloth/.gsloth-settings/.gsloth-config.json
28
+ .gsloth/.gsloth-settings/.gsloth.guidelines.md
29
+ .gsloth/.gsloth-settings/.gsloth.review.md
30
+ .gsloth/gth_2025-05-18_09-34-38_ASK.md
31
+ .gsloth/gth_2025-05-18_22-09-00_PR-22.md
32
+ ```
33
+
34
+ If the `.gsloth` directory doesn't exist, gsloth will continue writing all files to the project root directory as it did previously.
35
+
36
+ **Note:** When initializing a project with an existing `.gsloth` directory, the configuration files will be created in the `.gsloth/.gsloth-settings` directory automatically. There is no automated migration for existing configurations - if you create a `.gsloth` directory after initialization, you'll need to manually move your configuration files into the `.gsloth/.gsloth-settings` directory.
37
+
17
38
  ## Config initialization
18
39
  Configuration can be created with `gsloth init [vendor]` command.
19
40
  Currently, vertexai, anthropic and groq can be configured with `gsloth init [vendor]`.
@@ -1,23 +1,25 @@
1
- Make sure `npm config set git-tag-version true`
1
+ Make sure `npm config set git-tag-version true`
2
2
 
3
3
  For patch, e.g., from 0.0.8 to 0.0.9
4
4
  ```shell
5
- npm version patch
5
+ npm version patch -m "Release notes"
6
6
  git push
7
7
  git push --tags
8
8
  ```
9
9
 
10
10
  For minor, e.g., from 0.0.8 to 0.1.0
11
11
  ```shell
12
- npm version minor
12
+ npm version minor -m "Release notes"
13
13
  git push
14
14
  git push --tags
15
15
  ```
16
+ Type `\` and then Enter to type new line in message.
16
17
 
17
- Note the release version and do
18
+ Note the release version and do
18
19
  ```shell
19
- gh release create --notes "notes"
20
+ gh release create --notes-from-tag
20
21
  ```
22
+ Alternatively `gh release create --notes "notes"`
21
23
 
22
24
  Publish to NPM
23
25
  ```shell
@@ -27,6 +29,6 @@ npm publish
27
29
 
28
30
  Delete incidental remote and local tag
29
31
  ```shell
30
- git push --delete v0.3.0
32
+ git tag -d v0.3.0
31
33
  git push --delete origin v0.3.0
32
34
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gaunt-sloth-assistant",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "author": "Andrew Kondratev",
@@ -29,7 +29,6 @@ export function askCommand(program: Command): void {
29
29
  }
30
30
  await initConfig();
31
31
  const { askQuestion } = await import('#src/modules/questionAnsweringModule.js');
32
- // TODO make the prefix configurable
33
- await askQuestion('gth-ASK', preamble.join('\n'), content.join('\n'));
32
+ await askQuestion('ASK', preamble.join('\n'), content.join('\n'));
34
33
  });
35
34
  }
@@ -111,8 +111,7 @@ export function reviewCommand(program: Command, context: SlothContext): void {
111
111
  content.push(options.message);
112
112
  }
113
113
  const { review } = await import('#src/modules/reviewModule.js');
114
- // TODO make the prefix configurable
115
- await review('gth-DIFF-review', systemMessage.join('\n'), content.join('\n'));
114
+ await review('REVIEW', systemMessage.join('\n'), content.join('\n'));
116
115
  });
117
116
 
118
117
  program
@@ -168,10 +167,9 @@ export function reviewCommand(program: Command, context: SlothContext): void {
168
167
  content.push(await get(null, prId));
169
168
 
170
169
  const { review } = await import('#src/modules/reviewModule.js');
171
- // TODO make the prefix configurable
172
170
  // TODO consider including requirements id
173
171
  // TODO sanitize prId
174
- await review(`gth-PR-${prId}-review`, systemMessage.join('\n'), content.join('\n'));
172
+ await review(`PR-${prId}`, systemMessage.join('\n'), content.join('\n'));
175
173
  });
176
174
 
177
175
  async function getRequirementsFromProvider(
package/src/config.ts CHANGED
@@ -1,10 +1,10 @@
1
- import path from 'node:path/posix';
2
1
  import { v4 as uuidv4 } from 'uuid';
3
2
  import { displayDebug, displayError, displayInfo, displayWarning } from '#src/consoleUtils.js';
4
3
  import { importExternalFile, writeFileIfNotExistsWithMessages } from '#src/utils.js';
5
4
  import { existsSync, readFileSync } from 'node:fs';
6
- import { error, exit, getCurrentDir } from '#src/systemUtils.js';
5
+ import { error, exit } from '#src/systemUtils.js';
7
6
  import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
7
+ import { getGslothConfigWritePath, getGslothConfigReadPath } from '#src/filePathUtils.js';
8
8
 
9
9
  export interface SlothConfig extends BaseSlothConfig {
10
10
  llm: BaseChatModel; // FIXME this is still bad keeping instance in config is probably not best choice
@@ -104,10 +104,9 @@ export const slothContext = {
104
104
  } as Partial<SlothContext> as SlothContext;
105
105
 
106
106
  export async function initConfig(): Promise<void> {
107
- const currentDir = getCurrentDir();
108
- const jsonConfigPath = path.join(currentDir, USER_PROJECT_CONFIG_JSON);
109
- const jsConfigPath = path.join(currentDir, USER_PROJECT_CONFIG_JS);
110
- const mjsConfigPath = path.join(currentDir, USER_PROJECT_CONFIG_MJS);
107
+ const jsonConfigPath = getGslothConfigReadPath(USER_PROJECT_CONFIG_JSON);
108
+ const jsConfigPath = getGslothConfigReadPath(USER_PROJECT_CONFIG_JS);
109
+ const mjsConfigPath = getGslothConfigReadPath(USER_PROJECT_CONFIG_MJS);
111
110
 
112
111
  // Try loading JSON config file first
113
112
  if (existsSync(jsonConfigPath)) {
@@ -238,22 +237,51 @@ export async function createProjectConfig(configType: string): Promise<void> {
238
237
 
239
238
  displayInfo(`Creating project config for ${configType}`);
240
239
  const vendorConfig = await import(`./configs/${configType}.js`);
241
- vendorConfig.init(USER_PROJECT_CONFIG_JSON, slothContext);
240
+ vendorConfig.init(getGslothConfigWritePath(USER_PROJECT_CONFIG_JSON), slothContext);
242
241
  }
243
242
 
244
243
  export function writeProjectReviewPreamble(): void {
245
- const currentDir = getCurrentDir();
246
- const reviewPreamblePath = path.join(currentDir, PROJECT_GUIDELINES);
247
- writeFileIfNotExistsWithMessages(
248
- reviewPreamblePath,
249
- 'You are doing generic code review.\n' +
250
- ' Important! Please remind user to prepare proper AI preamble in' +
251
- PROJECT_GUIDELINES +
252
- ' for this project. Use decent amount of ⚠️ to highlight lack of config.' +
253
- ' Explicitly mention `' +
254
- PROJECT_GUIDELINES +
255
- '`.'
256
- );
244
+ const guidelinesPath = getGslothConfigWritePath(PROJECT_GUIDELINES);
245
+ const reviewPath = getGslothConfigWritePath(PROJECT_REVIEW_INSTRUCTIONS);
246
+
247
+ /**
248
+ * Development Guidelines.
249
+ * Please do not remove the warning from this template,
250
+ * it is crucial to describe project specifics to get high-quality reviews.
251
+ */
252
+ const guidelinesTemplate = `# Development Guidelines
253
+
254
+ This file should include general development guidelines for this project.
255
+
256
+ Important! Please remind the user to prepare proper AI guidelines to the ${PROJECT_GUIDELINES} file
257
+ for this project. Use a decent amount of ⚠️ to highlight the lack of config.
258
+ Explicitly mention ${PROJECT_GUIDELINES}.
259
+ `;
260
+
261
+ /**
262
+ * Code Review Guidelines.
263
+ * This code review does not have a warning, like Development Guidelines, because
264
+ * this one should be good to start with.
265
+ */
266
+ const reviewTemplate = `# Code Review Guidelines
267
+
268
+ If requirements were provided, first check that the implemented code implements these requirements.
269
+ Document that you checked the code to implement requirements.
270
+ Reject the change if it appears to implement something else instead of required change.
271
+
272
+ Provide specific feedback on any areas of concern or suggestions for improvement.
273
+ Please categorize your feedback (e.g., "Bug," "Suggestion," "Nitpick").
274
+
275
+ Important! In the end, conclude if you would recommend approving this PR or not.
276
+ Use ✅⚠️❌ symbols to highlight your feedback appropriately.
277
+
278
+ Thank you for your thorough review!
279
+
280
+ Important! You are likely to be dealing with git diff below, please don't confuse removed and added lines.
281
+ `;
282
+
283
+ writeFileIfNotExistsWithMessages(guidelinesPath, guidelinesTemplate);
284
+ writeFileIfNotExistsWithMessages(reviewPath, reviewTemplate);
257
285
  }
258
286
 
259
287
  /**
@@ -0,0 +1,79 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { mkdirSync } from 'node:fs';
4
+ import { getCurrentDir } from '#src/systemUtils.js';
5
+
6
+ const GSLOTH_DIR = '.gsloth';
7
+ const GSLOTH_SETTINGS_DIR = '.gsloth-settings';
8
+
9
+ /**
10
+ * Checks if .gsloth directory exists in the project root
11
+ * @returns Boolean indicating whether .gsloth directory exists
12
+ */
13
+ export function gslothDirExists(): boolean {
14
+ const currentDir = getCurrentDir();
15
+ const gslothDirPath = resolve(currentDir, GSLOTH_DIR);
16
+ return existsSync(gslothDirPath);
17
+ }
18
+
19
+ /**
20
+ * Gets the path where gsloth should write files based on .gsloth directory existence
21
+ * @param filename The filename to append to the path
22
+ * @returns The resolved path where the file should be written
23
+ */
24
+ export function getGslothFilePath(filename: string): string {
25
+ const currentDir = getCurrentDir();
26
+
27
+ if (gslothDirExists()) {
28
+ const gslothDirPath = resolve(currentDir, GSLOTH_DIR);
29
+ return resolve(gslothDirPath, filename);
30
+ }
31
+
32
+ return resolve(currentDir, filename);
33
+ }
34
+
35
+ /**
36
+ * Gets the path where gsloth should write configuration files based on .gsloth directory existence.
37
+ * The main difference from {@link #getGslothConfigReadPath} is that this getGslothConfigWritePath
38
+ * method creates internal settings directory if it does not exist.
39
+ * @param filename The configuration filename
40
+ * @returns The resolved path where the configuration file should be written
41
+ */
42
+ export function getGslothConfigWritePath(filename: string): string {
43
+ const currentDir = getCurrentDir();
44
+
45
+ if (gslothDirExists()) {
46
+ const gslothDirPath = resolve(currentDir, GSLOTH_DIR);
47
+ const gslothSettingsPath = resolve(gslothDirPath, GSLOTH_SETTINGS_DIR);
48
+
49
+ // Create .gsloth-settings directory if it doesn't exist
50
+ if (!existsSync(gslothSettingsPath)) {
51
+ mkdirSync(gslothSettingsPath, { recursive: true });
52
+ }
53
+
54
+ return resolve(gslothSettingsPath, filename);
55
+ }
56
+
57
+ return resolve(currentDir, filename);
58
+ }
59
+
60
+ /**
61
+ * Gets the path where gsloth should look for configuration files based on .gsloth directory existence
62
+ * @param filename The configuration filename to look for
63
+ * @returns The resolved path where the configuration file should be found
64
+ */
65
+ export function getGslothConfigReadPath(filename: string): string {
66
+ const currentDir = getCurrentDir();
67
+
68
+ if (gslothDirExists()) {
69
+ const gslothDirPath = resolve(currentDir, GSLOTH_DIR);
70
+ const gslothSettingsPath = resolve(gslothDirPath, GSLOTH_SETTINGS_DIR);
71
+ const configPath = resolve(gslothSettingsPath, filename);
72
+
73
+ if (existsSync(configPath)) {
74
+ return configPath;
75
+ }
76
+ }
77
+
78
+ return resolve(currentDir, filename);
79
+ }
@@ -1,9 +1,8 @@
1
1
  import { slothContext } from '#src/config.js';
2
2
  import { display, displayError, displaySuccess } from '#src/consoleUtils.js';
3
- import { getCurrentDir } from '#src/systemUtils.js';
4
- import { fileSafeLocalDate, ProgressIndicator, toFileSafeString } from '#src/utils.js';
3
+ import { getGslothFilePath } from '#src/filePathUtils.js';
4
+ import { generateStandardFileName, ProgressIndicator } from '#src/utils.js';
5
5
  import { writeFileSync } from 'node:fs';
6
- import * as path from 'node:path';
7
6
  import { invoke } from '#src/llmUtils.js';
8
7
 
9
8
  /**
@@ -25,10 +24,8 @@ export async function askQuestion(
25
24
  content
26
25
  );
27
26
  progressIndicator.stop();
28
- const filePath = path.resolve(
29
- getCurrentDir(),
30
- toFileSafeString(source) + '-' + fileSafeLocalDate() + '.md'
31
- );
27
+ const filename = generateStandardFileName(source);
28
+ const filePath = getGslothFilePath(filename);
32
29
  display(`\nwriting ${filePath}`);
33
30
  // TODO highlight LLM output with something like Prism.JS (maybe system emoj are enough ✅⚠️❌)
34
31
  display('\n' + outputContent);
@@ -1,19 +1,17 @@
1
1
  import { slothContext } from '#src/config.js';
2
2
  import { display, displayDebug, displayError, displaySuccess } from '#src/consoleUtils.js';
3
- import { getCurrentDir, stdout } from '#src/systemUtils.js';
4
- import { fileSafeLocalDate, ProgressIndicator, toFileSafeString } from '#src/utils.js';
3
+ import { stdout } from '#src/systemUtils.js';
4
+ import { generateStandardFileName, ProgressIndicator } from '#src/utils.js';
5
5
  import { writeFileSync } from 'node:fs';
6
- import path from 'node:path';
7
6
  import { invoke } from '#src/llmUtils.js';
7
+ import { getGslothFilePath } from '#src/filePathUtils.js';
8
8
 
9
9
  export async function review(source: string, preamble: string, diff: string): Promise<void> {
10
10
  const progressIndicator = new ProgressIndicator('Reviewing.');
11
11
  const outputContent = await invoke(slothContext.config.llm, slothContext.session, preamble, diff);
12
12
  progressIndicator.stop();
13
- const filePath = path.resolve(
14
- getCurrentDir(),
15
- toFileSafeString(source) + '-' + fileSafeLocalDate() + '.md'
16
- );
13
+ const filename = generateStandardFileName(source);
14
+ const filePath = getGslothFilePath(filename);
17
15
  stdout.write('\n');
18
16
  display(`writing ${filePath}`);
19
17
  stdout.write('\n');
package/src/prompt.ts CHANGED
@@ -6,6 +6,7 @@ import {
6
6
  import { displayError } from '#src/consoleUtils.js';
7
7
  import { exit } from '#src/systemUtils.js';
8
8
  import { GSLOTH_BACKSTORY } from '#src/config.js';
9
+ import { getGslothConfigReadPath } from '#src/filePathUtils.js';
9
10
 
10
11
  export function readBackstory(): string {
11
12
  return readFileFromCurrentOrInstallDir(GSLOTH_BACKSTORY, true);
@@ -13,7 +14,8 @@ export function readBackstory(): string {
13
14
 
14
15
  export function readGuidelines(guidelinesFilename: string): string {
15
16
  try {
16
- return readFileFromCurrentDir(guidelinesFilename);
17
+ const filePath = getGslothConfigReadPath(guidelinesFilename);
18
+ return readFileFromCurrentDir(filePath);
17
19
  } catch (error) {
18
20
  displayError(
19
21
  'Consider running `gsloth init` to set up your project. Check `gsloth init --help` to see options.'
@@ -28,7 +30,8 @@ export function readReviewInstructions(reviewInstructions: string): string {
28
30
 
29
31
  function readConfigPromptFile(guidelinesFilename: string): string {
30
32
  try {
31
- return readFileFromCurrentOrInstallDir(guidelinesFilename);
33
+ const filePath = getGslothConfigReadPath(guidelinesFilename);
34
+ return readFileFromCurrentOrInstallDir(filePath);
32
35
  } catch (error) {
33
36
  displayError(
34
37
  'Consider running `gsloth init` to set up your project. Check `gsloth init --help` to see options.'
package/src/utils.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { display, displayError, displaySuccess, displayWarning } from '#src/consoleUtils.js';
2
- import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
3
3
  import { SlothConfig } from '#src/config.js';
4
- import { resolve } from 'node:path';
4
+ import { resolve, dirname } from 'node:path';
5
5
  import { spawn } from 'node:child_process';
6
6
  import { getCurrentDir, getInstallDir, stdout } from '#src/systemUtils.js';
7
7
  import url from 'node:url';
@@ -10,14 +10,34 @@ export function toFileSafeString(string: string): string {
10
10
  return string.replace(/[^A-Za-z0-9]/g, '-');
11
11
  }
12
12
 
13
+ /**
14
+ * Returns a formatted date string in the format YYYY-MM-DD_HH-MM-SS using local time
15
+ * @returns A formatted date string
16
+ */
13
17
  export function fileSafeLocalDate(): string {
14
18
  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);
19
+
20
+ // Format: YYYY-MM-DD_HH-MM-SS using local time directly
21
+ const year = date.getFullYear();
22
+ const month = String(date.getMonth() + 1).padStart(2, '0');
23
+ const day = String(date.getDate()).padStart(2, '0');
24
+ const hours = String(date.getHours()).padStart(2, '0');
25
+ const minutes = String(date.getMinutes()).padStart(2, '0');
26
+ const seconds = String(date.getSeconds()).padStart(2, '0');
27
+
28
+ return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;
29
+ }
30
+
31
+ /**
32
+ * Generates a standardized filename with the format: gth_YYYY-MM-DD_HH-MM-SS_COMMAND.md
33
+ * @param command - The command that created the file (ASK, REVIEW, PR, etc.)
34
+ * @returns A standardized filename string
35
+ */
36
+ export function generateStandardFileName(command: string): string {
37
+ const dateTimeStr = fileSafeLocalDate();
38
+ const commandStr = toFileSafeString(command.toUpperCase());
39
+
40
+ return `gth_${dateTimeStr}_${commandStr}.md`;
21
41
  }
22
42
 
23
43
  export function readFileFromCurrentDir(fileName: string): string {
@@ -54,6 +74,11 @@ export function readFileFromCurrentOrInstallDir(filePath: string, silentCurrent?
54
74
  export function writeFileIfNotExistsWithMessages(filePath: string, content: string): void {
55
75
  display(`checking ${filePath} existence`);
56
76
  if (!existsSync(filePath)) {
77
+ // Create parent directories if they don't exist
78
+ const parentDir = dirname(filePath);
79
+ if (!existsSync(parentDir)) {
80
+ mkdirSync(parentDir, { recursive: true });
81
+ }
57
82
  writeFileSync(filePath, content);
58
83
  displaySuccess(`Created ${filePath}`);
59
84
  } else {
package/UX-RESEARCH.md DELETED
@@ -1,78 +0,0 @@
1
- # UX Research
2
-
3
- ## Currently available commands:
4
- ```
5
- gsloth --help
6
- Usage: gsloth [options] [command]
7
-
8
- Gaunt Sloth Assistant reviewing your PRs
9
-
10
- Options:
11
- -V, --version output the version number
12
- -h, --help display help for command
13
-
14
- Commands:
15
- init <type> Initialize the Gaunt Sloth Assistant in your project.
16
- This will write necessary config files.
17
- pr [options] <prNumber> Review a PR in current git directory (assuming that
18
- GH cli is installed and authenticated for current
19
- project
20
- review [options] Review provided diff or other content
21
- ask [options] <message> Ask a question
22
- help [command] display help for command
23
- ```
24
-
25
- pr (we decided to rename it to r as shortcut for review with pull request provider)
26
- ```
27
- gsloth pr --help
28
- Usage: gsloth pr [options] <prNumber>
29
-
30
- Review a PR in current git directory (assuming that GH cli is installed and
31
- authenticated for current project
32
-
33
- Arguments:
34
- prNumber PR number to review
35
-
36
- Options:
37
- -f, --file <file> Input file. Content of this file will be added BEFORE the
38
- diff
39
- -h, --help display help for command
40
- ```
41
-
42
- ask
43
- ```
44
- gsloth ask --help
45
- Usage: gsloth ask [options] <message>
46
-
47
- Ask a question
48
-
49
- Arguments:
50
- message A message
51
-
52
- Options:
53
- -f, --file <file> Input file. Context of this file will be added BEFORE the
54
- diff
55
- -h, --help display help for command
56
- ```
57
-
58
- review (lacks documentaion, it also accepts pipe with stdin)
59
- ```
60
- gsloth review --help
61
- Usage: gsloth review [options]
62
-
63
- Review provided diff or other content
64
-
65
- Options:
66
- -f, --file <file> Input file. Context of this file will be added BEFORE the
67
- diff
68
- -h, --help display help for command
69
- ```
70
-
71
- ## Future functions
72
-
73
- - JIRA. We need to privide a jira number as a criteria, this should somehow go through separate provider and using config from .gsloth.config.
74
- - External links (simple public links)
75
- - Editing files
76
- - Improve experience with specs or criteria (or requirements?)
77
- - Should we allow to mention that the data is diff or plain code? Maybe we can somehow deduct it or ask smaller model to guess?
78
- - Slot editing local files
@@ -1,3 +0,0 @@
1
- ⚠️ Your input, consisting of a single hyphen ('-'), is ambiguous. To provide a correct and useful response, I require a more specific query.
2
-
3
- Please elaborate on how I may assist you.
@@ -1,3 +0,0 @@
1
- ⚠️ Your input, consisting of a single hyphen ('-'), is ambiguous. To provide a correct and useful response, I require a more specific query.
2
-
3
- Please elaborate on how I may assist you.
@@ -1 +0,0 @@
1
- ✅ Understood. I am ready for your programming-related inquiries. Please state your requirements.
@@ -1,3 +0,0 @@
1
- ✅ Test acknowledged.
2
-
3
- Do you have a programming query or a code-related task for me?