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.
Files changed (145) hide show
  1. package/{.gsloth.preamble.review.md → .gsloth.guidelines.md} +0 -8
  2. package/.gsloth.review.md +7 -0
  3. package/.prettierrc.json +9 -0
  4. package/README.md +177 -158
  5. package/ROADMAP.md +1 -1
  6. package/dist/commands/askCommand.d.ts +6 -0
  7. package/dist/commands/askCommand.js +27 -0
  8. package/dist/commands/askCommand.js.map +1 -0
  9. package/dist/commands/initCommand.d.ts +6 -0
  10. package/dist/commands/initCommand.js +16 -0
  11. package/dist/commands/initCommand.js.map +1 -0
  12. package/dist/commands/reviewCommand.d.ts +3 -0
  13. package/dist/commands/reviewCommand.js +142 -0
  14. package/dist/commands/reviewCommand.js.map +1 -0
  15. package/dist/config.d.ts +84 -0
  16. package/dist/config.js +180 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/configs/anthropic.d.ts +4 -0
  19. package/{src → dist}/configs/anthropic.js +45 -48
  20. package/dist/configs/anthropic.js.map +1 -0
  21. package/dist/configs/fake.d.ts +3 -0
  22. package/{src → dist}/configs/fake.js +11 -14
  23. package/dist/configs/fake.js.map +1 -0
  24. package/dist/configs/groq.d.ts +4 -0
  25. package/{src → dist}/configs/groq.js +10 -13
  26. package/dist/configs/groq.js.map +1 -0
  27. package/dist/configs/types.d.ts +14 -0
  28. package/dist/configs/types.js +2 -0
  29. package/dist/configs/types.js.map +1 -0
  30. package/dist/configs/vertexai.d.ts +4 -0
  31. package/{src → dist}/configs/vertexai.js +44 -47
  32. package/dist/configs/vertexai.js.map +1 -0
  33. package/dist/consoleUtils.d.ts +6 -0
  34. package/{src → dist}/consoleUtils.js +10 -15
  35. package/dist/consoleUtils.js.map +1 -0
  36. package/dist/index.d.ts +1 -0
  37. package/dist/index.js +26 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/llmUtils.d.ts +4 -0
  40. package/dist/llmUtils.js +39 -0
  41. package/dist/llmUtils.js.map +1 -0
  42. package/dist/modules/questionAnsweringModule.d.ts +7 -0
  43. package/dist/modules/questionAnsweringModule.js +33 -0
  44. package/dist/modules/questionAnsweringModule.js.map +1 -0
  45. package/dist/modules/reviewModule.d.ts +1 -0
  46. package/dist/modules/reviewModule.js +29 -0
  47. package/dist/modules/reviewModule.js.map +1 -0
  48. package/dist/modules/types.d.ts +18 -0
  49. package/dist/modules/types.js +2 -0
  50. package/dist/modules/types.js.map +1 -0
  51. package/dist/prompt.d.ts +8 -0
  52. package/dist/prompt.js +45 -0
  53. package/dist/prompt.js.map +1 -0
  54. package/dist/providers/file.d.ts +8 -0
  55. package/dist/providers/file.js +20 -0
  56. package/dist/providers/file.js.map +1 -0
  57. package/dist/providers/ghPrDiffProvider.d.ts +8 -0
  58. package/dist/providers/ghPrDiffProvider.js +16 -0
  59. package/dist/providers/ghPrDiffProvider.js.map +1 -0
  60. package/dist/providers/jiraIssueLegacyAccessTokenProvider.d.ts +8 -0
  61. package/dist/providers/jiraIssueLegacyAccessTokenProvider.js +62 -0
  62. package/dist/providers/jiraIssueLegacyAccessTokenProvider.js.map +1 -0
  63. package/dist/providers/jiraIssueLegacyProvider.d.ts +8 -0
  64. package/dist/providers/jiraIssueLegacyProvider.js +74 -0
  65. package/dist/providers/jiraIssueLegacyProvider.js.map +1 -0
  66. package/dist/providers/jiraIssueProvider.d.ts +11 -0
  67. package/dist/providers/jiraIssueProvider.js +96 -0
  68. package/dist/providers/jiraIssueProvider.js.map +1 -0
  69. package/dist/providers/text.d.ts +8 -0
  70. package/dist/providers/text.js +10 -0
  71. package/dist/providers/text.js.map +1 -0
  72. package/dist/providers/types.d.ts +21 -0
  73. package/dist/providers/types.js +2 -0
  74. package/dist/providers/types.js.map +1 -0
  75. package/dist/systemUtils.d.ts +32 -0
  76. package/dist/systemUtils.js +70 -0
  77. package/dist/systemUtils.js.map +1 -0
  78. package/dist/utils.d.ts +49 -0
  79. package/dist/utils.js +192 -0
  80. package/dist/utils.js.map +1 -0
  81. package/docs/CONFIGURATION.md +99 -10
  82. package/docs/RELEASE-HOWTO.md +7 -1
  83. package/eslint.config.js +99 -21
  84. package/gth-ASK-2025-05-16T14-11-39.md +3 -0
  85. package/gth-ASK-2025-05-16T14-18-27.md +3 -0
  86. package/gth-ASK-2025-05-16T14-18-56.md +1 -0
  87. package/gth-ASK-2025-05-16T14-41-20.md +3 -0
  88. package/gth-ASK-2025-05-16T14-43-31.md +51 -0
  89. package/gth-ASK-2025-05-16T16-05-52.md +62 -0
  90. package/gth-DIFF-review-2025-05-16T16-07-53.md +56 -0
  91. package/gth-DIFF-review-2025-05-16T16-18-55.md +292 -0
  92. package/index.js +10 -27
  93. package/package.json +26 -15
  94. package/src/commands/askCommand.ts +35 -0
  95. package/src/commands/initCommand.ts +19 -0
  96. package/src/commands/reviewCommand.ts +223 -0
  97. package/src/config.ts +269 -0
  98. package/src/configs/anthropic.ts +57 -0
  99. package/src/configs/fake.ts +15 -0
  100. package/src/configs/groq.ts +54 -0
  101. package/src/configs/vertexai.ts +53 -0
  102. package/src/consoleUtils.ts +33 -0
  103. package/src/index.ts +30 -0
  104. package/src/llmUtils.ts +54 -0
  105. package/src/modules/questionAnsweringModule.ts +44 -0
  106. package/src/modules/reviewModule.ts +31 -0
  107. package/src/modules/types.ts +23 -0
  108. package/src/prompt.ts +54 -0
  109. package/src/providers/file.ts +24 -0
  110. package/src/providers/ghPrDiffProvider.ts +20 -0
  111. package/src/providers/jiraIssueLegacyProvider.ts +103 -0
  112. package/src/providers/jiraIssueProvider.ts +133 -0
  113. package/src/providers/text.ts +14 -0
  114. package/src/providers/types.ts +24 -0
  115. package/src/systemUtils.ts +90 -0
  116. package/src/utils.ts +232 -0
  117. package/tsconfig.json +24 -0
  118. package/vitest.config.ts +13 -0
  119. package/.eslint.config.mjs +0 -72
  120. package/.github/dependabot.yml +0 -11
  121. package/.github/workflows/ci.yml +0 -33
  122. package/spec/.gsloth.config.js +0 -22
  123. package/spec/.gsloth.config.json +0 -25
  124. package/spec/askCommand.spec.js +0 -92
  125. package/spec/config.spec.js +0 -421
  126. package/spec/initCommand.spec.js +0 -55
  127. package/spec/predefinedConfigs.spec.js +0 -100
  128. package/spec/questionAnsweringModule.spec.js +0 -137
  129. package/spec/reviewCommand.spec.js +0 -222
  130. package/spec/reviewModule.spec.js +0 -28
  131. package/spec/support/jasmine.mjs +0 -14
  132. package/src/commands/askCommand.js +0 -27
  133. package/src/commands/initCommand.js +0 -17
  134. package/src/commands/reviewCommand.js +0 -154
  135. package/src/config.js +0 -177
  136. package/src/modules/questionAnsweringModule.js +0 -82
  137. package/src/modules/reviewModule.js +0 -70
  138. package/src/prompt.js +0 -34
  139. package/src/providers/file.js +0 -19
  140. package/src/providers/ghPrDiffProvider.js +0 -11
  141. package/src/providers/jiraIssueLegacyAccessTokenProvider.js +0 -84
  142. package/src/providers/text.js +0 -6
  143. package/src/systemUtils.js +0 -32
  144. package/src/utils.js +0 -173
  145. /package/{.gsloth.preamble.internal.md → .gsloth.backstory.md} +0 -0
@@ -0,0 +1,96 @@
1
+ import { display, displayError, displayWarning } from '#src/consoleUtils.js';
2
+ import { env } from '#src/systemUtils.js';
3
+ /**
4
+ * Gets Jira issue using Atlassian REST API v3 with Personal Access Token
5
+ *
6
+ * TODO we need to figure out how would this work with public jira.
7
+ *
8
+ * @param config Jira configuration
9
+ * @param issueId Jira issue ID
10
+ * @returns Jira issue content
11
+ */
12
+ export async function get(config, issueId) {
13
+ if (!config) {
14
+ displayWarning('No Jira config provided');
15
+ return null;
16
+ }
17
+ if (!issueId) {
18
+ displayWarning('No issue ID provided');
19
+ return null;
20
+ }
21
+ // Get username from environment variable or config
22
+ const username = env.JIRA_USERNAME || config.username;
23
+ if (!username) {
24
+ throw new Error('Missing JIRA username. The username can be defined as JIRA_USERNAME environment variable or as "username" in config.');
25
+ }
26
+ // Get token from environment variable or config
27
+ const token = env.JIRA_API_PAT_TOKEN || config.token;
28
+ if (!token) {
29
+ throw new Error('Missing JIRA PAT token. The token can be defined as JIRA_API_PAT_TOKEN environment variable or as "token" in config.');
30
+ }
31
+ // Get cloud ID from environment variable or config
32
+ const cloudId = env.JIRA_CLOUD_ID || config.cloudId;
33
+ if (!cloudId) {
34
+ throw new Error('Missing JIRA Cloud ID. The Cloud ID can be defined as JIRA_CLOUD_ID environment variable or as "cloudId" in config.');
35
+ }
36
+ try {
37
+ const issue = await getJiraIssue({
38
+ ...config,
39
+ username,
40
+ token,
41
+ cloudId,
42
+ }, issueId);
43
+ if (!issue) {
44
+ return null;
45
+ }
46
+ const summary = issue.fields.summary;
47
+ const description = issue.fields.description;
48
+ return `Jira Issue: ${issueId}\nSummary: ${summary}\n\nDescription:\n${description}`;
49
+ }
50
+ catch (error) {
51
+ displayError(`Failed to get Jira issue: ${error instanceof Error ? error.message : String(error)}`);
52
+ return null;
53
+ }
54
+ }
55
+ /**
56
+ * Helper function to get Jira issue details using Atlassian REST API v3
57
+ * @param config Jira configuration
58
+ * @param jiraKey Jira issue ID
59
+ * @returns Jira issue response
60
+ */
61
+ async function getJiraIssue(config, jiraKey) {
62
+ // Jira Cloud ID can be found by authenticated user at https://company.atlassian.net/_edge/tenant_info
63
+ // According to doc https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-get permissions to read this resource:
64
+ // either Classic (RECOMMENDED) read:jira-work
65
+ // or Granular read:issue-meta:jira, read:issue-security-level:jira, read:issue.vote:jira, read:issue.changelog:jira, read:avatar:jira, read:issue:jira, read:status:jira, read:user:jira, read:field-configuration:jira
66
+ const apiUrl = `https://api.atlassian.com/ex/jira/${config.cloudId}/rest/api/3/issue/${jiraKey}`;
67
+ if (config.displayUrl) {
68
+ display(`Loading Jira issue ${config.displayUrl}${jiraKey}`);
69
+ }
70
+ display(`Retrieving jira from api ${apiUrl.replace(/^https?:\/\//, '')}`);
71
+ // Encode credentials for Basic Authentication header
72
+ const credentials = `${config.username}:${config.token}`;
73
+ const encodedCredentials = Buffer.from(credentials).toString('base64');
74
+ const authHeader = `Basic ${encodedCredentials}`;
75
+ // Define request headers
76
+ const headers = {
77
+ Authorization: authHeader,
78
+ Accept: 'application/json; charset=utf-8',
79
+ 'Accept-Language': 'en-US,en;q=0.9', // Prevents errors in other languages
80
+ };
81
+ const response = await fetch(apiUrl, {
82
+ method: 'GET',
83
+ headers: headers,
84
+ });
85
+ if (!response?.ok) {
86
+ try {
87
+ const errorData = await response.json();
88
+ throw new Error(`Failed to fetch Jira issue: ${response.statusText} - ${JSON.stringify(errorData)}`);
89
+ }
90
+ catch (_e) {
91
+ throw new Error(`Failed to fetch Jira issue: ${response?.statusText}`);
92
+ }
93
+ }
94
+ return response.json();
95
+ }
96
+ //# sourceMappingURL=jiraIssueProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jiraIssueProvider.js","sourceRoot":"","sources":["../../src/providers/jiraIssueProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAY1C;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,MAAkC,EAClC,OAA2B;IAE3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,cAAc,CAAC,yBAAyB,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,cAAc,CAAC,sBAAsB,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mDAAmD;IACnD,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,IAAI,MAAM,CAAC,QAAQ,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,sHAAsH,CACvH,CAAC;IACJ,CAAC;IAED,gDAAgD;IAChD,MAAM,KAAK,GAAG,GAAG,CAAC,kBAAkB,IAAI,MAAM,CAAC,KAAK,CAAC;IACrD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,sHAAsH,CACvH,CAAC;IACJ,CAAC;IAED,mDAAmD;IACnD,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,IAAI,MAAM,CAAC,OAAO,CAAC;IACpD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,qHAAqH,CACtH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,YAAY,CAC9B;YACE,GAAG,MAAM;YACT,QAAQ;YACR,KAAK;YACL,OAAO;SACR,EACD,OAAO,CACR,CAAC;QACF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC;QACrC,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC;QAE7C,OAAO,eAAe,OAAO,cAAc,OAAO,qBAAqB,WAAW,EAAE,CAAC;IACvF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,YAAY,CACV,6BAA6B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACtF,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,YAAY,CAAC,MAAkB,EAAE,OAAe;IAC7D,sGAAsG;IAEtG,0KAA0K;IAC1K,8CAA8C;IAC9C,wNAAwN;IACxN,MAAM,MAAM,GAAG,qCAAqC,MAAM,CAAC,OAAO,qBAAqB,OAAO,EAAE,CAAC;IACjG,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,OAAO,CAAC,sBAAsB,MAAM,CAAC,UAAU,GAAG,OAAO,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,CAAC,4BAA4B,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAE1E,qDAAqD;IACrD,MAAM,WAAW,GAAG,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;IACzD,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,SAAS,kBAAkB,EAAE,CAAC;IAEjD,yBAAyB;IACzB,MAAM,OAAO,GAAG;QACd,aAAa,EAAE,UAAU;QACzB,MAAM,EAAE,iCAAiC;QACzC,iBAAiB,EAAE,gBAAgB,EAAE,qCAAqC;KAC3E,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;QACnC,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CACb,+BAA+B,QAAQ,CAAC,UAAU,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CACpF,CAAC;QACJ,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ProviderConfig } from './types.js';
2
+ /**
3
+ * Returns the provided text as is
4
+ * @param _ config (unused in this provider)
5
+ * @param text Text to return
6
+ * @returns The provided text
7
+ */
8
+ export declare function get(_: ProviderConfig | null, text: string | undefined): Promise<string | null>;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Returns the provided text as is
3
+ * @param _ config (unused in this provider)
4
+ * @param text Text to return
5
+ * @returns The provided text
6
+ */
7
+ export async function get(_, text) {
8
+ return text ?? null;
9
+ }
10
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/providers/text.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,CAAwB,EACxB,IAAwB;IAExB,OAAO,IAAI,IAAI,IAAI,CAAC;AACtB,CAAC"}
@@ -0,0 +1,21 @@
1
+ export interface ProviderConfig {
2
+ username?: string;
3
+ token?: string;
4
+ baseUrl?: string;
5
+ [key: string]: unknown;
6
+ }
7
+ export interface JiraLegacyConfig extends ProviderConfig {
8
+ username: string;
9
+ baseUrl: string;
10
+ displayUrl?: string;
11
+ token: string;
12
+ }
13
+ export interface JiraConfig extends ProviderConfig {
14
+ cloudId: string;
15
+ username: string;
16
+ displayUrl?: string;
17
+ token: string;
18
+ }
19
+ export interface Provider {
20
+ get: (config: ProviderConfig | null, id: string | undefined) => Promise<string | null>;
21
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import { Command } from 'commander';
2
+ export declare const getCurrentDir: () => string;
3
+ export declare const getInstallDir: () => string;
4
+ /**
5
+ * Cached string from stdin. Should only be called after readStdin completes execution.
6
+ */
7
+ export declare const getStringFromStdin: () => string;
8
+ export declare const exit: (code?: number) => never;
9
+ export declare const stdin: NodeJS.ReadStream & {
10
+ fd: 0;
11
+ };
12
+ export declare const stdout: NodeJS.WriteStream & {
13
+ fd: 1;
14
+ };
15
+ export declare const argv: string[];
16
+ export declare const env: NodeJS.ProcessEnv;
17
+ /**
18
+ * Provide the path to the entry point of the application.
19
+ * This is used to set the install directory.
20
+ * This is called from index.js root entry point.
21
+ */
22
+ export declare const setEntryPoint: (indexJs: string) => void;
23
+ /**
24
+ * Asynchronously reads the stdin and stores it as a string,
25
+ * it can later be retrieved with getStringFromStdin.
26
+ */
27
+ export declare function readStdin(program: Command): Promise<void>;
28
+ export declare const log: (message: string) => void;
29
+ export declare const error: (message: string) => void;
30
+ export declare const warn: (message: string) => void;
31
+ export declare const info: (message: string) => void;
32
+ export declare const debug: (message: string) => void;
@@ -0,0 +1,70 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { fileURLToPath } from 'url';
3
+ import { ProgressIndicator } from '#src/utils.js';
4
+ const innerState = {
5
+ installDir: undefined,
6
+ stringFromStdin: '',
7
+ };
8
+ // Process-related functions and objects
9
+ export const getCurrentDir = () => process.cwd();
10
+ export const getInstallDir = () => {
11
+ if (innerState.installDir) {
12
+ return innerState.installDir;
13
+ }
14
+ throw new Error('Install directory not set');
15
+ };
16
+ /**
17
+ * Cached string from stdin. Should only be called after readStdin completes execution.
18
+ */
19
+ export const getStringFromStdin = () => {
20
+ return innerState.stringFromStdin;
21
+ };
22
+ export const exit = (code) => process.exit(code || 0);
23
+ export const stdin = process.stdin;
24
+ export const stdout = process.stdout;
25
+ export const argv = process.argv;
26
+ export const env = process.env;
27
+ // noinspection JSUnusedGlobalSymbols
28
+ /**
29
+ * Provide the path to the entry point of the application.
30
+ * This is used to set the install directory.
31
+ * This is called from index.js root entry point.
32
+ */
33
+ export const setEntryPoint = (indexJs) => {
34
+ const filePath = fileURLToPath(indexJs);
35
+ const dirPath = dirname(filePath);
36
+ innerState.installDir = resolve(dirPath);
37
+ };
38
+ /**
39
+ * Asynchronously reads the stdin and stores it as a string,
40
+ * it can later be retrieved with getStringFromStdin.
41
+ */
42
+ export function readStdin(program) {
43
+ return new Promise((resolvePromise) => {
44
+ if (stdin.isTTY) {
45
+ program.parseAsync().then(() => resolvePromise());
46
+ }
47
+ else {
48
+ // Support piping diff into gsloth
49
+ const progressIndicator = new ProgressIndicator('reading STDIN', true);
50
+ stdin.on('readable', function () {
51
+ const chunk = this.read();
52
+ progressIndicator.indicate();
53
+ if (chunk !== null) {
54
+ const chunkStr = chunk.toString('utf8');
55
+ innerState.stringFromStdin = innerState.stringFromStdin + chunkStr;
56
+ }
57
+ });
58
+ stdin.on('end', function () {
59
+ program.parseAsync(argv).then(() => resolvePromise());
60
+ });
61
+ }
62
+ });
63
+ }
64
+ // Console-related functions
65
+ export const log = (message) => console.log(message);
66
+ export const error = (message) => console.error(message);
67
+ export const warn = (message) => console.warn(message);
68
+ export const info = (message) => console.info(message);
69
+ export const debug = (message) => console.debug(message);
70
+ //# sourceMappingURL=systemUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemUtils.js","sourceRoot":"","sources":["../src/systemUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { SlothConfig } from '#src/config.js';
2
+ export declare function toFileSafeString(string: string): string;
3
+ export declare function fileSafeLocalDate(): string;
4
+ export declare function readFileFromCurrentDir(fileName: string): string;
5
+ export declare function readFileFromCurrentOrInstallDir(filePath: string, silentCurrent?: boolean): string;
6
+ export declare function writeFileIfNotExistsWithMessages(filePath: string, content: string): void;
7
+ export declare function readFileSyncWithMessages(filePath: string, errorMessageIn?: string, noFileMessage?: string): string;
8
+ export declare function spawnCommand(command: string, args: string[], progressMessage: string, successMessage: string): Promise<string>;
9
+ export declare function getSlothVersion(): string;
10
+ export declare class ProgressIndicator {
11
+ private interval;
12
+ constructor(initialMessage: string, manual?: boolean);
13
+ private indicateInner;
14
+ indicate(): void;
15
+ stop(): void;
16
+ }
17
+ interface LLMOutput {
18
+ messages: Array<{
19
+ content: string;
20
+ }>;
21
+ }
22
+ /**
23
+ * Extracts the content of the last message from an LLM response
24
+ * @param output - The output from the LLM containing messages
25
+ * @returns The content of the last message
26
+ */
27
+ export declare function extractLastMessageContent(output: LLMOutput): string;
28
+ /**
29
+ * Dynamically imports a module from a file path from the outside of the installation dir
30
+ * @param filePath - The path to the file to import
31
+ * @returns A promise that resolves to the imported module
32
+ */
33
+ export declare function importExternalFile(filePath: string): Promise<{
34
+ configure: (module: string) => Promise<Partial<SlothConfig>>;
35
+ }>;
36
+ /**
37
+ * Alias for importExternalFile for backward compatibility with tests
38
+ * @param filePath - The path to the file to import
39
+ * @returns A promise that resolves to the imported module
40
+ */
41
+ export declare const importFromFilePath: typeof importExternalFile;
42
+ /**
43
+ * Reads multiple files from the current directory and returns their contents
44
+ * @param fileNames - Array of file names to read
45
+ * @returns Combined content of all files with proper formatting
46
+ */
47
+ export declare function readMultipleFilesFromCurrentDir(fileNames: string | string[]): string;
48
+ export declare function execAsync(command: string): Promise<string>;
49
+ export {};
package/dist/utils.js ADDED
@@ -0,0 +1,192 @@
1
+ import { display, displayError, displaySuccess, displayWarning } from '#src/consoleUtils.js';
2
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ import { spawn } from 'node:child_process';
5
+ import { getCurrentDir, getInstallDir, stdout } from '#src/systemUtils.js';
6
+ import url from 'node:url';
7
+ export function toFileSafeString(string) {
8
+ return string.replace(/[^A-Za-z0-9]/g, '-');
9
+ }
10
+ export function fileSafeLocalDate() {
11
+ 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);
18
+ }
19
+ export function readFileFromCurrentDir(fileName) {
20
+ const currentDir = getCurrentDir();
21
+ const filePath = resolve(currentDir, fileName);
22
+ display(`Reading file ${filePath}...`);
23
+ return readFileSyncWithMessages(filePath);
24
+ }
25
+ export function readFileFromCurrentOrInstallDir(filePath, silentCurrent) {
26
+ const currentDir = getCurrentDir();
27
+ const currentFilePath = resolve(currentDir, filePath);
28
+ if (!silentCurrent) {
29
+ display(`Reading file ${currentFilePath}...`);
30
+ }
31
+ try {
32
+ return readFileSync(currentFilePath, { encoding: 'utf8' });
33
+ }
34
+ catch (_error) {
35
+ if (!silentCurrent) {
36
+ display(`The ${currentFilePath} not found or can\'t be read, trying install directory...`);
37
+ }
38
+ const installDir = getInstallDir();
39
+ const installFilePath = resolve(installDir, filePath);
40
+ try {
41
+ return readFileSync(installFilePath, { encoding: 'utf8' });
42
+ }
43
+ catch (readFromInstallDirError) {
44
+ displayError(`The ${installFilePath} not found or can\'t be read.`);
45
+ throw readFromInstallDirError;
46
+ }
47
+ }
48
+ }
49
+ export function writeFileIfNotExistsWithMessages(filePath, content) {
50
+ display(`checking ${filePath} existence`);
51
+ if (!existsSync(filePath)) {
52
+ writeFileSync(filePath, content);
53
+ displaySuccess(`Created ${filePath}`);
54
+ }
55
+ else {
56
+ displayWarning(`${filePath} already exists`);
57
+ }
58
+ }
59
+ export function readFileSyncWithMessages(filePath, errorMessageIn, noFileMessage) {
60
+ const errorMessage = errorMessageIn ?? 'Error reading file at: ';
61
+ try {
62
+ return readFileSync(filePath, { encoding: 'utf8' });
63
+ }
64
+ catch (error) {
65
+ displayError(errorMessage + filePath);
66
+ if (error.code === 'ENOENT') {
67
+ displayWarning(noFileMessage ?? 'Please ensure the file exists.');
68
+ }
69
+ else {
70
+ displayError(error.message);
71
+ }
72
+ throw error;
73
+ }
74
+ }
75
+ export async function spawnCommand(command, args, progressMessage, successMessage) {
76
+ return new Promise((resolve, reject) => {
77
+ const progressIndicator = new ProgressIndicator(progressMessage, true);
78
+ const out = { stdout: '', stderr: '' };
79
+ const spawned = spawn(command, args);
80
+ spawned.stdout.on('data', async (stdoutChunk) => {
81
+ progressIndicator.indicate();
82
+ out.stdout += stdoutChunk.toString();
83
+ });
84
+ spawned.stderr.on('data', (err) => {
85
+ progressIndicator.indicate();
86
+ out.stderr += err.toString();
87
+ });
88
+ spawned.on('error', (err) => {
89
+ reject(err.toString());
90
+ });
91
+ spawned.on('close', (code) => {
92
+ if (code === 0) {
93
+ display(successMessage);
94
+ resolve(out.stdout);
95
+ }
96
+ else {
97
+ displayError(`Failed to spawn command with code ${code}`);
98
+ reject(out.stdout + ' ' + out.stderr);
99
+ }
100
+ });
101
+ });
102
+ }
103
+ export function getSlothVersion() {
104
+ // TODO figure out if this can be injected with TS
105
+ const installDir = getInstallDir();
106
+ const jsonPath = resolve(installDir, 'package.json');
107
+ const projectJson = readFileSync(jsonPath, { encoding: 'utf8' });
108
+ return JSON.parse(projectJson).version;
109
+ }
110
+ export class ProgressIndicator {
111
+ interval = undefined;
112
+ constructor(initialMessage, manual) {
113
+ stdout.write(initialMessage);
114
+ if (!manual) {
115
+ this.interval = setInterval(this.indicateInner, 1000);
116
+ }
117
+ }
118
+ indicateInner() {
119
+ stdout.write('.');
120
+ }
121
+ indicate() {
122
+ if (this.interval) {
123
+ throw new Error('ProgressIndicator.indicate only to be called in manual mode');
124
+ }
125
+ this.indicateInner();
126
+ }
127
+ stop() {
128
+ if (this.interval) {
129
+ clearInterval(this.interval);
130
+ }
131
+ stdout.write('\n');
132
+ }
133
+ }
134
+ /**
135
+ * Extracts the content of the last message from an LLM response
136
+ * @param output - The output from the LLM containing messages
137
+ * @returns The content of the last message
138
+ */
139
+ export function extractLastMessageContent(output) {
140
+ if (!output || !output.messages || !output.messages.length) {
141
+ return '';
142
+ }
143
+ return output.messages[output.messages.length - 1].content;
144
+ }
145
+ /**
146
+ * Dynamically imports a module from a file path from the outside of the installation dir
147
+ * @param filePath - The path to the file to import
148
+ * @returns A promise that resolves to the imported module
149
+ */
150
+ export function importExternalFile(filePath) {
151
+ const configFileUrl = url.pathToFileURL(filePath).toString();
152
+ return import(configFileUrl);
153
+ }
154
+ /**
155
+ * Alias for importExternalFile for backward compatibility with tests
156
+ * @param filePath - The path to the file to import
157
+ * @returns A promise that resolves to the imported module
158
+ */
159
+ export const importFromFilePath = importExternalFile;
160
+ /**
161
+ * Reads multiple files from the current directory and returns their contents
162
+ * @param fileNames - Array of file names to read
163
+ * @returns Combined content of all files with proper formatting
164
+ */
165
+ export function readMultipleFilesFromCurrentDir(fileNames) {
166
+ if (!Array.isArray(fileNames)) {
167
+ return readFileFromCurrentDir(fileNames);
168
+ }
169
+ return fileNames
170
+ .map((fileName) => {
171
+ const content = readFileFromCurrentDir(fileName);
172
+ return `${fileName}:\n\`\`\`\n${content}\n\`\`\``;
173
+ })
174
+ .join('\n\n');
175
+ }
176
+ export async function execAsync(command) {
177
+ const { exec } = await import('node:child_process');
178
+ return new Promise((resolve, reject) => {
179
+ exec(command, (error, stdout, stderr) => {
180
+ if (error) {
181
+ reject(error);
182
+ return;
183
+ }
184
+ if (stderr) {
185
+ reject(new Error(stderr));
186
+ return;
187
+ }
188
+ resolve(stdout.trim());
189
+ });
190
+ });
191
+ }
192
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}