gaunt-sloth-assistant 0.1.4 → 0.2.2

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 (128) hide show
  1. package/.prettierrc.json +9 -0
  2. package/README.md +177 -158
  3. package/ROADMAP.md +1 -1
  4. package/dist/commands/askCommand.d.ts +6 -0
  5. package/dist/commands/askCommand.js +26 -0
  6. package/dist/commands/askCommand.js.map +1 -0
  7. package/dist/commands/initCommand.d.ts +6 -0
  8. package/dist/commands/initCommand.js +16 -0
  9. package/dist/commands/initCommand.js.map +1 -0
  10. package/dist/commands/reviewCommand.d.ts +3 -0
  11. package/dist/commands/reviewCommand.js +128 -0
  12. package/dist/commands/reviewCommand.js.map +1 -0
  13. package/dist/config.d.ts +80 -0
  14. package/dist/config.js +178 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/configs/anthropic.d.ts +5 -0
  17. package/{src → dist}/configs/anthropic.js +45 -48
  18. package/dist/configs/anthropic.js.map +1 -0
  19. package/dist/configs/fake.d.ts +3 -0
  20. package/{src → dist}/configs/fake.js +11 -14
  21. package/dist/configs/fake.js.map +1 -0
  22. package/dist/configs/groq.d.ts +4 -0
  23. package/{src → dist}/configs/groq.js +10 -13
  24. package/dist/configs/groq.js.map +1 -0
  25. package/dist/configs/types.d.ts +14 -0
  26. package/dist/configs/types.js +2 -0
  27. package/dist/configs/types.js.map +1 -0
  28. package/dist/configs/vertexai.d.ts +4 -0
  29. package/{src → dist}/configs/vertexai.js +44 -47
  30. package/dist/configs/vertexai.js.map +1 -0
  31. package/dist/consoleUtils.d.ts +6 -0
  32. package/{src → dist}/consoleUtils.js +10 -15
  33. package/dist/consoleUtils.js.map +1 -0
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.js +17 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/modules/questionAnsweringModule.d.ts +18 -0
  38. package/{src → dist}/modules/questionAnsweringModule.js +72 -82
  39. package/dist/modules/questionAnsweringModule.js.map +1 -0
  40. package/dist/modules/reviewModule.d.ts +4 -0
  41. package/{src → dist}/modules/reviewModule.js +25 -35
  42. package/dist/modules/reviewModule.js.map +1 -0
  43. package/dist/modules/types.d.ts +18 -0
  44. package/dist/modules/types.js +2 -0
  45. package/dist/modules/types.js.map +1 -0
  46. package/dist/prompt.d.ts +7 -0
  47. package/dist/prompt.js +32 -0
  48. package/dist/prompt.js.map +1 -0
  49. package/dist/providers/file.d.ts +8 -0
  50. package/dist/providers/file.js +20 -0
  51. package/dist/providers/file.js.map +1 -0
  52. package/dist/providers/ghPrDiffProvider.d.ts +8 -0
  53. package/dist/providers/ghPrDiffProvider.js +16 -0
  54. package/dist/providers/ghPrDiffProvider.js.map +1 -0
  55. package/dist/providers/jiraIssueLegacyAccessTokenProvider.d.ts +8 -0
  56. package/dist/providers/jiraIssueLegacyAccessTokenProvider.js +62 -0
  57. package/dist/providers/jiraIssueLegacyAccessTokenProvider.js.map +1 -0
  58. package/dist/providers/jiraIssueLegacyProvider.d.ts +8 -0
  59. package/dist/providers/jiraIssueLegacyProvider.js +74 -0
  60. package/dist/providers/jiraIssueLegacyProvider.js.map +1 -0
  61. package/dist/providers/jiraIssueProvider.d.ts +11 -0
  62. package/dist/providers/jiraIssueProvider.js +96 -0
  63. package/dist/providers/jiraIssueProvider.js.map +1 -0
  64. package/dist/providers/text.d.ts +8 -0
  65. package/dist/providers/text.js +10 -0
  66. package/dist/providers/text.js.map +1 -0
  67. package/dist/providers/types.d.ts +21 -0
  68. package/dist/providers/types.js +2 -0
  69. package/dist/providers/types.js.map +1 -0
  70. package/dist/systemUtils.d.ts +22 -0
  71. package/dist/systemUtils.js +36 -0
  72. package/dist/systemUtils.js.map +1 -0
  73. package/dist/utils.d.ts +49 -0
  74. package/{src → dist}/utils.js +73 -60
  75. package/dist/utils.js.map +1 -0
  76. package/docs/CONFIGURATION.md +95 -6
  77. package/docs/RELEASE-HOWTO.md +1 -1
  78. package/eslint.config.js +99 -21
  79. package/index.js +10 -27
  80. package/package.json +26 -15
  81. package/src/commands/askCommand.ts +34 -0
  82. package/src/commands/initCommand.ts +19 -0
  83. package/src/commands/reviewCommand.ts +209 -0
  84. package/src/config.ts +266 -0
  85. package/src/configs/anthropic.ts +55 -0
  86. package/src/configs/fake.ts +15 -0
  87. package/src/configs/groq.ts +54 -0
  88. package/src/configs/vertexai.ts +53 -0
  89. package/src/consoleUtils.ts +33 -0
  90. package/src/index.ts +21 -0
  91. package/src/modules/questionAnsweringModule.ts +97 -0
  92. package/src/modules/reviewModule.ts +81 -0
  93. package/src/modules/types.ts +23 -0
  94. package/src/prompt.ts +39 -0
  95. package/src/providers/file.ts +24 -0
  96. package/src/providers/ghPrDiffProvider.ts +20 -0
  97. package/src/providers/jiraIssueLegacyProvider.ts +103 -0
  98. package/src/providers/jiraIssueProvider.ts +133 -0
  99. package/src/providers/text.ts +14 -0
  100. package/src/providers/types.ts +24 -0
  101. package/src/systemUtils.ts +52 -0
  102. package/src/utils.ts +225 -0
  103. package/tsconfig.json +24 -0
  104. package/vitest.config.ts +13 -0
  105. package/.eslint.config.mjs +0 -72
  106. package/.github/dependabot.yml +0 -11
  107. package/.github/workflows/ci.yml +0 -33
  108. package/spec/.gsloth.config.js +0 -22
  109. package/spec/.gsloth.config.json +0 -25
  110. package/spec/askCommand.spec.js +0 -92
  111. package/spec/config.spec.js +0 -421
  112. package/spec/initCommand.spec.js +0 -55
  113. package/spec/predefinedConfigs.spec.js +0 -100
  114. package/spec/questionAnsweringModule.spec.js +0 -137
  115. package/spec/reviewCommand.spec.js +0 -222
  116. package/spec/reviewModule.spec.js +0 -28
  117. package/spec/support/jasmine.mjs +0 -14
  118. package/src/commands/askCommand.js +0 -27
  119. package/src/commands/initCommand.js +0 -17
  120. package/src/commands/reviewCommand.js +0 -154
  121. package/src/config.js +0 -177
  122. package/src/prompt.js +0 -34
  123. package/src/providers/file.js +0 -19
  124. package/src/providers/ghPrDiffProvider.js +0 -11
  125. package/src/providers/jiraIssueLegacyAccessTokenProvider.js +0 -84
  126. package/src/providers/text.js +0 -6
  127. package/src/systemUtils.js +0 -32
  128. /package/{.gsloth.preamble.internal.md → .gsloth.backstory.md} +0 -0
@@ -1,82 +1,72 @@
1
- import {END, MemorySaver, MessagesAnnotation, START, StateGraph,} from "@langchain/langgraph";
2
- import {writeFileSync} from "node:fs";
3
- import * as path from "node:path";
4
- import {slothContext} from "../config.js";
5
- import {display, displayError, displaySuccess} from "../consoleUtils.js";
6
- import {extractLastMessageContent, fileSafeLocalDate, ProgressIndicator, toFileSafeString} from "../utils.js";
7
- import {getCurrentDir} from "../systemUtils.js";
8
-
9
- /**
10
- * Ask a question and get an answer from the LLM
11
- * @param {string} source - The source of the question (used for file naming)
12
- * @param {string} preamble - The preamble to send to the LLM
13
- * @param {string} content - The content of the question
14
- */
15
- export async function askQuestion(source, preamble, content) {
16
- const progressIndicator = new ProgressIndicator("Thinking.");
17
- const outputContent = await askQuestionInner(slothContext, () => progressIndicator.indicate(), preamble, content);
18
- const filePath = path.resolve(getCurrentDir(), toFileSafeString(source)+'-'+fileSafeLocalDate()+".md");
19
- display(`\nwriting ${filePath}`);
20
- // TODO highlight LLM output with something like Prism.JS
21
- display('\n' + outputContent);
22
- try {
23
- writeFileSync(filePath, outputContent);
24
- displaySuccess(`This report can be found in ${filePath}`);
25
- } catch (error) {
26
- displayError(`Failed to write answer to file: ${filePath}`);
27
- displayError(error.message);
28
- // TODO Consider if we want to exit or just log the error
29
- // exit(1);
30
- }
31
- }
32
-
33
- /**
34
- * Inner function to ask a question and get an answer from the LLM
35
- * @param {Object} context - The context object
36
- * @param {Function} indicateProgress - Function to indicate progress
37
- * @param {string} preamble - The preamble to send to the LLM
38
- * @param {string} content - The content of the question
39
- * @returns {string} The answer from the LLM
40
- */
41
- export async function askQuestionInner(context, indicateProgress, preamble, content) {
42
- // This node receives the current state (messages) and invokes the LLM
43
- const callModel = async (state) => {
44
- // state.messages will contain the list including the system preamble and user diff
45
- const response = await context.config.llm.invoke(state.messages);
46
- // MessagesAnnotation expects the node to return the new message(s) to be added to the state.
47
- // Wrap the response in an array if it's a single message object.
48
- return { messages: response };
49
- };
50
-
51
- // Define the graph structure with MessagesAnnotation state
52
- const workflow = new StateGraph(MessagesAnnotation)
53
- // Define the node and edge
54
- .addNode("model", callModel)
55
- .addEdge(START, "model") // Start at the 'model' node
56
- .addEdge("model", END); // End after the 'model' node completes
57
-
58
- // Set up memory (optional but good practice for potential future multi-turn interactions)
59
- const memory = new MemorySaver();
60
-
61
- // Compile the workflow into a runnable app
62
- const app = workflow.compile({ checkpointer: memory });
63
-
64
- // Construct the initial the messages including the preamble as a system message
65
- const messages = [
66
- {
67
- role: "system",
68
- content: preamble, // The preamble goes here
69
- },
70
- {
71
- role: "user",
72
- content, // The question goes here
73
- },
74
- ];
75
-
76
- indicateProgress();
77
- // TODO create proper progress indicator for async tasks.
78
- const progress = setInterval(() => indicateProgress(), 1000);
79
- const output = await app.invoke({messages}, context.session);
80
- clearInterval(progress);
81
- return extractLastMessageContent(output);
82
- }
1
+ import { slothContext } from '#src/config.js';
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';
5
+ import { HumanMessage, SystemMessage } from '@langchain/core/messages';
6
+ import { END, MemorySaver, MessagesAnnotation, START, StateGraph } from '@langchain/langgraph';
7
+ import { writeFileSync } from 'node:fs';
8
+ import * as path from 'node:path';
9
+ /**
10
+ * Ask a question and get an answer from the LLM
11
+ * @param source - The source of the question (used for file naming)
12
+ * @param preamble - The preamble to send to the LLM
13
+ * @param content - The content of the question
14
+ */
15
+ export async function askQuestion(source, preamble, content) {
16
+ const progressIndicator = new ProgressIndicator('Thinking.');
17
+ const outputContent = await askQuestionInner(slothContext, () => progressIndicator.indicate(), preamble, content);
18
+ const filePath = path.resolve(getCurrentDir(), toFileSafeString(source) + '-' + fileSafeLocalDate() + '.md');
19
+ display(`\nwriting ${filePath}`);
20
+ // TODO highlight LLM output with something like Prism.JS
21
+ display('\n' + outputContent);
22
+ try {
23
+ writeFileSync(filePath, outputContent);
24
+ displaySuccess(`This report can be found in ${filePath}`);
25
+ }
26
+ catch (error) {
27
+ displayError(`Failed to write answer to file: ${filePath}`);
28
+ displayError(error instanceof Error ? error.message : String(error));
29
+ // TODO Consider if we want to exit or just log the error
30
+ // exit(1);
31
+ }
32
+ }
33
+ /**
34
+ * Inner function to ask a question and get an answer from the LLM
35
+ * @param context - The context object
36
+ * @param indicateProgress - Function to indicate progress
37
+ * @param preamble - The preamble to send to the LLM
38
+ * @param content - The content of the question
39
+ * @returns The answer from the LLM
40
+ */
41
+ export async function askQuestionInner(context, indicateProgress, preamble, content) {
42
+ // This node receives the current state (messages) and invokes the LLM
43
+ const callModel = async (state) => {
44
+ // state.messages will contain the list including the system preamble and user diff
45
+ const response = await context.config.llm.invoke(state.messages);
46
+ // MessagesAnnotation expects the node to return the new message(s) to be added to the state.
47
+ // Wrap the response in an array if it's a single message object.
48
+ return { messages: response };
49
+ };
50
+ // Define the graph structure with MessagesAnnotation state
51
+ const workflow = new StateGraph(MessagesAnnotation)
52
+ // Define the node and edge
53
+ .addNode('model', callModel)
54
+ .addEdge(START, 'model') // Start at the 'model' node
55
+ .addEdge('model', END); // End after the 'model' node completes
56
+ // Set up memory (optional but good practice for potential future multi-turn interactions)
57
+ const memory = new MemorySaver();
58
+ // Compile the workflow into a runnable app
59
+ const app = workflow.compile({ checkpointer: memory });
60
+ // Construct the initial the messages including the preamble as a system message
61
+ const messages = [new SystemMessage(preamble), new HumanMessage(content)];
62
+ indicateProgress();
63
+ // TODO create proper progress indicator for async tasks.
64
+ const progress = setInterval(() => indicateProgress(), 1000);
65
+ const output = await app.invoke({ messages }, context.session);
66
+ clearInterval(progress);
67
+ const lastMessage = output.messages[output.messages.length - 1];
68
+ return typeof lastMessage.content === 'string'
69
+ ? lastMessage.content
70
+ : JSON.stringify(lastMessage.content);
71
+ }
72
+ //# sourceMappingURL=questionAnsweringModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"questionAnsweringModule.js","sourceRoot":"","sources":["../../src/modules/questionAnsweringModule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SlothContext } from '#src/config.js';
2
+ import type { ProgressCallback } from '#src/modules/types.js';
3
+ export declare function review(source: string, preamble: string, diff: string): Promise<void>;
4
+ export declare function reviewInner(context: SlothContext, indicateProgress: ProgressCallback, preamble: string, diff: string): Promise<string>;
@@ -1,31 +1,31 @@
1
- import {END, MemorySaver, MessagesAnnotation, START, StateGraph,} from "@langchain/langgraph";
2
- import {writeFileSync} from "node:fs";
3
- import path from "node:path";
4
- import {slothContext} from "../config.js";
5
- import {display, displayDebug, displayError, displaySuccess} from "../consoleUtils.js";
6
- import {extractLastMessageContent, fileSafeLocalDate, ProgressIndicator, toFileSafeString} from "../utils.js";
7
- import {getCurrentDir, stdout} from "../systemUtils.js";
8
-
1
+ import { slothContext } from '#src/config.js';
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';
5
+ import { HumanMessage, SystemMessage } from '@langchain/core/messages';
6
+ import { END, MemorySaver, MessagesAnnotation, START, StateGraph } from '@langchain/langgraph';
7
+ import { writeFileSync } from 'node:fs';
8
+ import path from 'node:path';
9
9
  export async function review(source, preamble, diff) {
10
- const progressIndicator = new ProgressIndicator("Reviewing.");
10
+ const progressIndicator = new ProgressIndicator('Reviewing.');
11
11
  const outputContent = await reviewInner(slothContext, () => progressIndicator.indicate(), preamble, diff);
12
- const filePath = path.resolve(getCurrentDir(), toFileSafeString(source)+'-'+fileSafeLocalDate()+".md");
13
- stdout.write("\n");
12
+ const filePath = path.resolve(getCurrentDir(), toFileSafeString(source) + '-' + fileSafeLocalDate() + '.md');
13
+ stdout.write('\n');
14
14
  display(`writing ${filePath}`);
15
- stdout.write("\n");
15
+ stdout.write('\n');
16
16
  // TODO highlight LLM output with something like Prism.JS (maybe system emoj are enough ✅⚠️❌)
17
17
  display(outputContent);
18
18
  try {
19
19
  writeFileSync(filePath, outputContent);
20
20
  displaySuccess(`This report can be found in ${filePath}`);
21
- } catch (error) {
22
- displayDebug(error);
21
+ }
22
+ catch (error) {
23
+ displayDebug(error instanceof Error ? error : String(error));
23
24
  displayError(`Failed to write review to file: ${filePath}`);
24
25
  // Consider if you want to exit or just log the error
25
26
  // exit(1);
26
27
  }
27
28
  }
28
-
29
29
  export async function reviewInner(context, indicateProgress, preamble, diff) {
30
30
  // This node receives the current state (messages) and invokes the LLM
31
31
  const callModel = async (state) => {
@@ -35,36 +35,26 @@ export async function reviewInner(context, indicateProgress, preamble, diff) {
35
35
  // Wrap the response in an array if it's a single message object.
36
36
  return { messages: response };
37
37
  };
38
-
39
38
  // Define the graph structure with MessagesAnnotation state
40
39
  const workflow = new StateGraph(MessagesAnnotation)
41
40
  // Define the node and edge
42
- .addNode("model", callModel)
43
- .addEdge(START, "model") // Start at the 'model' node
44
- .addEdge("model", END); // End after the 'model' node completes
45
-
41
+ .addNode('model', callModel)
42
+ .addEdge(START, 'model') // Start at the 'model' node
43
+ .addEdge('model', END); // End after the 'model' node completes
46
44
  // Set up memory (optional but good practice for potential future multi-turn interactions)
47
45
  const memory = new MemorySaver(); // TODO extract to config
48
-
49
46
  // Compile the workflow into a runnable app
50
47
  const app = workflow.compile({ checkpointer: memory });
51
-
52
48
  // Construct the initial the messages including the preamble as a system message
53
- const messages = [
54
- {
55
- role: "system",
56
- content: preamble, // The preamble goes here
57
- },
58
- {
59
- role: "user",
60
- content: diff, // The code diff goes here
61
- },
62
- ];
63
-
49
+ const messages = [new SystemMessage(preamble), new HumanMessage(diff)];
64
50
  indicateProgress();
65
51
  // TODO create proper progress indicator for async tasks.
66
52
  const progress = setInterval(() => indicateProgress(), 1000);
67
- const output = await app.invoke({messages}, context.session);
53
+ const output = await app.invoke({ messages }, context.session);
68
54
  clearInterval(progress);
69
- return extractLastMessageContent(output);
55
+ const lastMessage = output.messages[output.messages.length - 1];
56
+ return typeof lastMessage.content === 'string'
57
+ ? lastMessage.content
58
+ : JSON.stringify(lastMessage.content);
70
59
  }
60
+ //# sourceMappingURL=reviewModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewModule.js","sourceRoot":"","sources":["../../src/modules/reviewModule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { BaseMessage } from '@langchain/core/messages';
2
+ export type Message = BaseMessage;
3
+ export interface State {
4
+ messages: Message[];
5
+ }
6
+ export interface ProgressCallback {
7
+ (): void;
8
+ }
9
+ export interface ReviewOptions {
10
+ source: string;
11
+ preamble: string;
12
+ diff: string;
13
+ }
14
+ export interface QuestionOptions {
15
+ source: string;
16
+ preamble: string;
17
+ content: string;
18
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/modules/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ export declare function readInternalPreamble(): string;
2
+ export declare function readPreamble(preambleFilename: string): string;
3
+ /**
4
+ * This function expects https://cli.github.com/ to be installed and authenticated.
5
+ * It does something like `gh pr diff 42`
6
+ */
7
+ export declare function getPrDiff(pr: string): Promise<string>;
package/dist/prompt.js ADDED
@@ -0,0 +1,32 @@
1
+ import { resolve } from 'node:path';
2
+ import { GSLOTH_BACKSTORY } from '#src/config.js';
3
+ import { readFileSyncWithMessages, spawnCommand } from '#src/utils.js';
4
+ import { displayError } from '#src/consoleUtils.js';
5
+ import { exit, getCurrentDir, getInstallDir } from '#src/systemUtils.js';
6
+ export function readInternalPreamble() {
7
+ const installDir = getInstallDir();
8
+ const filePath = resolve(installDir, GSLOTH_BACKSTORY);
9
+ return readFileSyncWithMessages(filePath, 'Error reading internal preamble file at:') || '';
10
+ }
11
+ export function readPreamble(preambleFilename) {
12
+ const currentDir = getCurrentDir();
13
+ const filePath = resolve(currentDir, preambleFilename);
14
+ return (readFileSyncWithMessages(filePath, 'Error reading preamble file at:', 'Consider running `gsloth init` to set up your project. Check `gsloth init --help` to see options.') || '');
15
+ }
16
+ /**
17
+ * This function expects https://cli.github.com/ to be installed and authenticated.
18
+ * It does something like `gh pr diff 42`
19
+ */
20
+ export async function getPrDiff(pr) {
21
+ // TODO makes sense to check if gh is available and authenticated
22
+ try {
23
+ return await spawnCommand('gh', ['pr', 'diff', pr], 'Loading PR diff...', 'Loaded PR diff.');
24
+ }
25
+ catch (e) {
26
+ displayError(e instanceof Error ? e.toString() : String(e));
27
+ displayError(`Failed to call "gh pr diff ${pr}", see message above for details.`);
28
+ exit();
29
+ return ''; // This line will never be reached due to exit()
30
+ }
31
+ }
32
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzE,MAAM,UAAU,oBAAoB;IAClC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;IACvD,OAAO,wBAAwB,CAAC,QAAQ,EAAE,0CAA0C,CAAC,IAAI,EAAE,CAAC;AAC9F,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,gBAAwB;IACnD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;IACvD,OAAO,CACL,wBAAwB,CACtB,QAAQ,EACR,iCAAiC,EACjC,mGAAmG,CACpG,IAAI,EAAE,CACR,CAAC;AACJ,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"}
@@ -0,0 +1,8 @@
1
+ import type { ProviderConfig } from './types.js';
2
+ /**
3
+ * Reads the text file from current dir
4
+ * @param _ config (unused in this provider)
5
+ * @param fileName
6
+ * @returns file contents
7
+ */
8
+ export declare function get(_: ProviderConfig | null, fileName: string | undefined): Promise<string | null>;
@@ -0,0 +1,20 @@
1
+ import { resolve } from 'node:path';
2
+ import { display } from '#src/consoleUtils.js';
3
+ import { readFileSyncWithMessages } from '#src/utils.js';
4
+ import { getCurrentDir } from '#src/systemUtils.js';
5
+ /**
6
+ * Reads the text file from current dir
7
+ * @param _ config (unused in this provider)
8
+ * @param fileName
9
+ * @returns file contents
10
+ */
11
+ export async function get(_, fileName) {
12
+ if (!fileName) {
13
+ return null;
14
+ }
15
+ const currentDir = getCurrentDir();
16
+ const filePath = resolve(currentDir, fileName);
17
+ display(`Reading file ${fileName}...`);
18
+ return readFileSyncWithMessages(filePath);
19
+ }
20
+ //# sourceMappingURL=file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/providers/file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,CAAwB,EACxB,QAA4B;IAE5B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC/C,OAAO,CAAC,gBAAgB,QAAQ,KAAK,CAAC,CAAC;IACvC,OAAO,wBAAwB,CAAC,QAAQ,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ProviderConfig } from './types.js';
2
+ /**
3
+ * Gets PR diff using gh command line tool
4
+ * @param _ config (unused in this provider)
5
+ * @param pr PR number
6
+ * @returns PR diff
7
+ */
8
+ export declare function get(_: ProviderConfig | null, pr: string | undefined): Promise<string | null>;
@@ -0,0 +1,16 @@
1
+ import { displayWarning } from '#src/consoleUtils.js';
2
+ import { execAsync } from '#src/utils.js';
3
+ /**
4
+ * Gets PR diff using gh command line tool
5
+ * @param _ config (unused in this provider)
6
+ * @param pr PR number
7
+ * @returns PR diff
8
+ */
9
+ export async function get(_, pr) {
10
+ if (!pr) {
11
+ displayWarning('No PR provided');
12
+ return null;
13
+ }
14
+ return execAsync(`gh pr diff ${pr}`);
15
+ }
16
+ //# sourceMappingURL=ghPrDiffProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ghPrDiffProvider.js","sourceRoot":"","sources":["../../src/providers/ghPrDiffProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAG1C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,CAAwB,EACxB,EAAsB;IAEtB,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,cAAc,CAAC,gBAAgB,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,SAAS,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { JiraConfig } from "./types.js";
2
+ /**
3
+ * Gets Jira issue using Atlassian REST API v2
4
+ * @param config Jira configuration
5
+ * @param issueId Jira issue ID
6
+ * @returns Jira issue content
7
+ */
8
+ export declare function get(config: JiraConfig | null, issueId: string | undefined): Promise<string | null>;
@@ -0,0 +1,62 @@
1
+ import { displayError, displayWarning } from "#src/consoleUtils.js";
2
+ /**
3
+ * Gets Jira issue using Atlassian REST API v2
4
+ * @param config Jira configuration
5
+ * @param issueId Jira issue ID
6
+ * @returns Jira issue content
7
+ */
8
+ export async function get(config, issueId) {
9
+ if (!config) {
10
+ displayWarning("No Jira config provided");
11
+ return null;
12
+ }
13
+ if (!issueId) {
14
+ displayWarning("No issue ID provided");
15
+ return null;
16
+ }
17
+ if (!config.username) {
18
+ displayWarning("No Jira username provided");
19
+ return null;
20
+ }
21
+ if (!config.baseUrl) {
22
+ displayWarning("No Jira base URL provided");
23
+ return null;
24
+ }
25
+ if (!config.token) {
26
+ displayWarning("No Jira token provided");
27
+ return null;
28
+ }
29
+ try {
30
+ const issue = await getJiraIssue(config, issueId);
31
+ if (!issue) {
32
+ return null;
33
+ }
34
+ const summary = issue.fields.summary;
35
+ const description = issue.fields.description;
36
+ return `Jira Issue: ${issueId}\nSummary: ${summary}\n\nDescription:\n${description}`;
37
+ }
38
+ catch (error) {
39
+ displayError(`Failed to get Jira issue: ${error instanceof Error ? error.message : String(error)}`);
40
+ return null;
41
+ }
42
+ }
43
+ /**
44
+ * Helper function to get Jira issue details
45
+ * @param config Jira configuration
46
+ * @param issueId Jira issue ID
47
+ * @returns Jira issue response
48
+ */
49
+ async function getJiraIssue(config, issueId) {
50
+ const auth = Buffer.from(`${config.username}:${config.token}`).toString('base64');
51
+ const response = await fetch(`${config.baseUrl}/rest/api/2/issue/${issueId}`, {
52
+ headers: {
53
+ 'Authorization': `Basic ${auth}`,
54
+ 'Accept': 'application/json'
55
+ }
56
+ });
57
+ if (!response.ok) {
58
+ throw new Error(`Failed to fetch Jira issue: ${response.statusText}`);
59
+ }
60
+ return response.json();
61
+ }
62
+ //# sourceMappingURL=jiraIssueLegacyAccessTokenProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jiraIssueLegacyAccessTokenProvider.js","sourceRoot":"","sources":["../../src/providers/jiraIssueLegacyAccessTokenProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAYpE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,MAAyB,EAAE,OAA2B;IAC5E,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,cAAc,CAAC,yBAAyB,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,cAAc,CAAC,sBAAsB,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACnB,cAAc,CAAC,2BAA2B,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAClB,cAAc,CAAC,2BAA2B,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAChB,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QAChB,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;IACzF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,YAAY,CAAC,6BAA6B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACpG,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,YAAY,CAAC,MAAkB,EAAE,OAAe;IAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,qBAAqB,OAAO,EAAE,EAAE;QAC1E,OAAO,EAAE;YACL,eAAe,EAAE,SAAS,IAAI,EAAE;YAChC,QAAQ,EAAE,kBAAkB;SAC/B;KACJ,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { JiraLegacyConfig } from '#src/providers/types.js';
2
+ /**
3
+ * Gets Jira issue using Atlassian REST API v2 with unscoped API token (aka Legacy Token)
4
+ * @param config Jira configuration
5
+ * @param issueId Jira issue ID
6
+ * @returns Jira issue content
7
+ */
8
+ export declare function get(config: Partial<JiraLegacyConfig>, issueId: string | undefined): Promise<string | null>;
@@ -0,0 +1,74 @@
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 v2 with unscoped API token (aka Legacy Token)
5
+ * @param config Jira configuration
6
+ * @param issueId Jira issue ID
7
+ * @returns Jira issue content
8
+ */
9
+ export async function get(config, issueId) {
10
+ if (!config) {
11
+ displayWarning('No Jira config provided');
12
+ return null;
13
+ }
14
+ if (!issueId) {
15
+ displayWarning('No issue ID provided');
16
+ return null;
17
+ }
18
+ if (!config.baseUrl) {
19
+ displayWarning('No Jira base URL provided');
20
+ return null;
21
+ }
22
+ // Get username from environment variable or config
23
+ const username = env.JIRA_USERNAME || config.username;
24
+ if (!username) {
25
+ throw new Error('Missing JIRA username. The username can be defined as JIRA_USERNAME environment variable or as "username" in config.');
26
+ }
27
+ // Get token from environment variable or config
28
+ const token = env.JIRA_LEGACY_API_TOKEN || config.token;
29
+ if (!token) {
30
+ throw new Error('Missing JIRA Legacy API token. The legacy token can be defined as JIRA_LEGACY_API_TOKEN environment variable or as "token" in config.');
31
+ }
32
+ try {
33
+ const issue = await getJiraIssue({
34
+ ...config,
35
+ username,
36
+ token,
37
+ }, issueId);
38
+ if (!issue) {
39
+ return null;
40
+ }
41
+ const summary = issue.fields.summary;
42
+ const description = issue.fields.description;
43
+ return `Jira Issue: ${issueId}\nSummary: ${summary}\n\nDescription:\n${description}`;
44
+ }
45
+ catch (error) {
46
+ displayError(`Failed to get Jira issue: ${error instanceof Error ? error.message : String(error)}`);
47
+ return null;
48
+ }
49
+ }
50
+ /**
51
+ * Helper function to get Jira issue details
52
+ * @param config Jira configuration
53
+ * @param issueId Jira issue ID
54
+ * @returns Jira issue response
55
+ */
56
+ async function getJiraIssue(config, issueId) {
57
+ const auth = Buffer.from(`${config.username}:${config.token}`).toString('base64');
58
+ const url = `${config.baseUrl}${issueId}`;
59
+ if (config.displayUrl) {
60
+ display(`Loading Jira issue ${config.displayUrl}${issueId}`);
61
+ }
62
+ display(`Retrieving jira from api ${url.replace(/^https?:\/\//, '')}`);
63
+ const response = await fetch(url, {
64
+ headers: {
65
+ Authorization: `Basic ${auth}`,
66
+ Accept: 'application/json',
67
+ },
68
+ });
69
+ if (!response.ok) {
70
+ throw new Error(`Failed to fetch Jira issue from ${url} with status: ${response.statusText}`);
71
+ }
72
+ return response.json();
73
+ }
74
+ //# sourceMappingURL=jiraIssueLegacyProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jiraIssueLegacyProvider.js","sourceRoot":"","sources":["../../src/providers/jiraIssueLegacyProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { JiraConfig } from './types.js';
2
+ /**
3
+ * Gets Jira issue using Atlassian REST API v3 with Personal Access Token
4
+ *
5
+ * TODO we need to figure out how would this work with public jira.
6
+ *
7
+ * @param config Jira configuration
8
+ * @param issueId Jira issue ID
9
+ * @returns Jira issue content
10
+ */
11
+ export declare function get(config: Partial<JiraConfig> | null, issueId: string | undefined): Promise<string | null>;