gaunt-sloth-assistant 0.6.0 → 0.6.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.
- package/.gsloth.backstory.md +0 -0
- package/.gsloth.chat.md +0 -0
- package/.gsloth.code.md +0 -0
- package/.gsloth.guidelines.md +0 -0
- package/.gsloth.review.md +0 -0
- package/.gsloth.system.md +0 -0
- package/.prettierrc.json +0 -0
- package/LICENSE +0 -0
- package/README.md +0 -0
- package/assets/gaunt-sloth-logo.png +0 -0
- package/assets/release-notes/v0_4_0.md +0 -0
- package/assets/release-notes/v0_5_0.md +0 -0
- package/assets/release-notes/v0_5_1.md +0 -0
- package/assets/release-notes/v0_5_2.md +0 -0
- package/assets/release-notes/v0_5_3.md +0 -0
- package/assets/release-notes/v0_6_0.md +0 -0
- package/assets/release-notes/v0_6_2.md +4 -0
- package/dist/commands/askCommand.d.ts +0 -0
- package/dist/commands/askCommand.js +0 -0
- package/dist/commands/askCommand.js.map +0 -0
- package/dist/commands/chatCommand.d.ts +0 -0
- package/dist/commands/chatCommand.js +10 -79
- package/dist/commands/chatCommand.js.map +1 -1
- package/dist/commands/codeCommand.d.ts +0 -4
- package/dist/commands/codeCommand.js +10 -83
- package/dist/commands/codeCommand.js.map +1 -1
- package/dist/commands/commandUtils.d.ts +0 -0
- package/dist/commands/commandUtils.js +0 -0
- package/dist/commands/commandUtils.js.map +0 -0
- package/dist/commands/initCommand.d.ts +0 -0
- package/dist/commands/initCommand.js +0 -0
- package/dist/commands/initCommand.js.map +0 -0
- package/dist/commands/prCommand.d.ts +0 -0
- package/dist/commands/prCommand.js +0 -0
- package/dist/commands/prCommand.js.map +0 -0
- package/dist/commands/reviewCommand.d.ts +0 -0
- package/dist/commands/reviewCommand.js +0 -0
- package/dist/commands/reviewCommand.js.map +0 -0
- package/dist/config.d.ts +0 -0
- package/dist/config.js +0 -0
- package/dist/config.js.map +0 -0
- package/dist/configs/anthropic.d.ts +0 -0
- package/dist/configs/anthropic.js +0 -0
- package/dist/configs/anthropic.js.map +0 -0
- package/dist/configs/fake.d.ts +0 -0
- package/dist/configs/fake.js +0 -0
- package/dist/configs/fake.js.map +0 -0
- package/dist/configs/groq.d.ts +0 -0
- package/dist/configs/groq.js +0 -0
- package/dist/configs/groq.js.map +0 -0
- package/dist/configs/vertexai.d.ts +0 -0
- package/dist/configs/vertexai.js +0 -0
- package/dist/configs/vertexai.js.map +0 -0
- package/dist/consoleUtils.d.ts +2 -0
- package/dist/consoleUtils.js +26 -0
- package/dist/consoleUtils.js.map +1 -1
- package/dist/constants.d.ts +0 -0
- package/dist/constants.js +0 -0
- package/dist/constants.js.map +0 -0
- package/dist/core/Invocation.d.ts +22 -0
- package/dist/core/Invocation.js +155 -0
- package/dist/core/Invocation.js.map +1 -0
- package/dist/core/types.d.ts +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/filePathUtils.d.ts +0 -0
- package/dist/filePathUtils.js +0 -0
- package/dist/filePathUtils.js.map +0 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js.map +0 -0
- package/dist/llmUtils.d.ts +0 -0
- package/dist/llmUtils.js +28 -124
- package/dist/llmUtils.js.map +1 -1
- package/dist/modules/interactiveSessionModule.d.ts +8 -0
- package/dist/modules/interactiveSessionModule.js +82 -0
- package/dist/modules/interactiveSessionModule.js.map +1 -0
- package/dist/modules/questionAnsweringModule.d.ts +0 -0
- package/dist/modules/questionAnsweringModule.js +0 -0
- package/dist/modules/questionAnsweringModule.js.map +0 -0
- package/dist/modules/reviewModule.d.ts +0 -0
- package/dist/modules/reviewModule.js +0 -0
- package/dist/modules/reviewModule.js.map +0 -0
- package/dist/modules/types.d.ts +0 -0
- package/dist/modules/types.js +0 -0
- package/dist/modules/types.js.map +0 -0
- package/dist/prompt.d.ts +0 -0
- package/dist/prompt.js +0 -0
- package/dist/prompt.js.map +0 -0
- package/dist/providers/file.d.ts +0 -0
- package/dist/providers/file.js +0 -0
- package/dist/providers/file.js.map +0 -0
- package/dist/providers/ghIssueProvider.d.ts +0 -0
- package/dist/providers/ghIssueProvider.js +0 -0
- package/dist/providers/ghIssueProvider.js.map +0 -0
- package/dist/providers/ghPrDiffProvider.d.ts +0 -0
- package/dist/providers/ghPrDiffProvider.js +0 -0
- package/dist/providers/ghPrDiffProvider.js.map +0 -0
- package/dist/providers/jiraIssueLegacyProvider.d.ts +0 -0
- package/dist/providers/jiraIssueLegacyProvider.js +0 -0
- package/dist/providers/jiraIssueLegacyProvider.js.map +0 -0
- package/dist/providers/jiraIssueProvider.d.ts +0 -0
- package/dist/providers/jiraIssueProvider.js +0 -0
- package/dist/providers/jiraIssueProvider.js.map +0 -0
- package/dist/providers/text.d.ts +0 -0
- package/dist/providers/text.js +0 -0
- package/dist/providers/text.js.map +0 -0
- package/dist/providers/types.d.ts +0 -0
- package/dist/providers/types.js +0 -0
- package/dist/providers/types.js.map +0 -0
- package/dist/systemUtils.d.ts +0 -0
- package/dist/systemUtils.js +0 -0
- package/dist/systemUtils.js.map +0 -0
- package/dist/utils.d.ts +0 -0
- package/dist/utils.js +0 -0
- package/dist/utils.js.map +0 -0
- package/docs/COMMANDS.md +0 -0
- package/docs/CONFIGURATION.md +0 -0
- package/docs/DEVELOPMENT.md +0 -0
- package/docs/RELEASE-HOWTO.md +0 -0
- package/eslint.config.js +0 -0
- package/maintenance/doc-maintenance.md +0 -0
- package/package.json +2 -2
- package/req/70-refactor-to-facilitate-imports.md +46 -0
- package/req/70a-extract-invocation.md +26 -0
- package/src/commands/askCommand.ts +0 -0
- package/src/commands/chatCommand.ts +11 -90
- package/src/commands/codeCommand.ts +12 -94
- package/src/commands/commandUtils.ts +0 -0
- package/src/commands/initCommand.ts +0 -0
- package/src/commands/prCommand.ts +0 -0
- package/src/commands/reviewCommand.ts +0 -0
- package/src/config.ts +0 -0
- package/src/configs/anthropic.ts +0 -0
- package/src/configs/fake.ts +0 -0
- package/src/configs/groq.ts +0 -0
- package/src/configs/vertexai.ts +0 -0
- package/src/consoleUtils.ts +32 -0
- package/src/constants.ts +0 -0
- package/src/core/Invocation.ts +198 -0
- package/src/core/types.ts +1 -0
- package/src/filePathUtils.ts +0 -0
- package/src/index.ts +0 -0
- package/src/llmUtils.ts +29 -142
- package/src/modules/interactiveSessionModule.ts +104 -0
- package/src/modules/questionAnsweringModule.ts +0 -0
- package/src/modules/reviewModule.ts +0 -0
- package/src/modules/types.ts +0 -0
- package/src/prompt.ts +0 -0
- package/src/providers/file.ts +0 -0
- package/src/providers/ghIssueProvider.ts +0 -0
- package/src/providers/ghPrDiffProvider.ts +0 -0
- package/src/providers/jiraIssueLegacyProvider.ts +0 -0
- package/src/providers/jiraIssueProvider.ts +0 -0
- package/src/providers/text.ts +0 -0
- package/src/providers/types.ts +0 -0
- package/src/systemUtils.ts +0 -0
- package/src/utils.ts +0 -0
- package/tsconfig.json +0 -0
- package/vitest-it.config.ts +2 -4
- package/vitest.config.ts +0 -0
package/dist/index.d.ts
CHANGED
|
File without changes
|
package/dist/index.js.map
CHANGED
|
File without changes
|
package/dist/llmUtils.d.ts
CHANGED
|
File without changes
|
package/dist/llmUtils.js
CHANGED
|
@@ -1,139 +1,43 @@
|
|
|
1
|
-
import { isAIMessage } from '@langchain/core/messages';
|
|
2
|
-
import { MultiServerMCPClient } from '@langchain/mcp-adapters';
|
|
3
1
|
import { display, displayError, displayInfo, displayWarning } from '#src/consoleUtils.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { ProgressIndicator } from '#src/utils.js';
|
|
2
|
+
import { stdout } from '#src/systemUtils.js';
|
|
3
|
+
import { Invocation } from '#src/core/Invocation.js';
|
|
7
4
|
const llmGlobalSettings = {
|
|
8
5
|
verbose: false,
|
|
9
6
|
};
|
|
10
7
|
export async function invoke(command, messages, config, runConfig, checkpointSaver) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
const statusUpdate = (level, message) => {
|
|
9
|
+
switch (level) {
|
|
10
|
+
case 'display':
|
|
11
|
+
display(message);
|
|
12
|
+
break;
|
|
13
|
+
case 'info':
|
|
14
|
+
displayInfo(message);
|
|
15
|
+
break;
|
|
16
|
+
case 'warning':
|
|
17
|
+
displayWarning(message);
|
|
18
|
+
break;
|
|
19
|
+
case 'error':
|
|
20
|
+
displayError(message);
|
|
21
|
+
break;
|
|
22
|
+
case 'stream':
|
|
23
|
+
stdout.write(message, 'utf-8');
|
|
24
|
+
break;
|
|
25
|
+
default:
|
|
26
|
+
display(message);
|
|
27
|
+
break;
|
|
15
28
|
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
config.llm.verbose = true;
|
|
20
|
-
}
|
|
21
|
-
// Merge command-specific filesystem config if provided
|
|
22
|
-
let effectiveConfig = config;
|
|
23
|
-
if (command && config.commands?.[command]?.filesystem !== undefined) {
|
|
24
|
-
effectiveConfig = {
|
|
25
|
-
...config,
|
|
26
|
-
filesystem: config.commands[command].filesystem,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
const client = getClient(effectiveConfig);
|
|
30
|
-
const allTools = (await client?.getTools()) ?? [];
|
|
31
|
-
const tools = filterTools(allTools, effectiveConfig.filesystem || 'none');
|
|
32
|
-
if (allTools.length > 0) {
|
|
33
|
-
displayInfo(`Loaded ${tools.length} tools.`);
|
|
34
|
-
}
|
|
35
|
-
// Create the React agent
|
|
36
|
-
const agent = createReactAgent({
|
|
37
|
-
llm: config.llm,
|
|
38
|
-
tools,
|
|
39
|
-
checkpointSaver,
|
|
40
|
-
});
|
|
41
|
-
// Run the agent
|
|
29
|
+
};
|
|
30
|
+
const invocation = new Invocation(statusUpdate);
|
|
31
|
+
invocation.setVerbose(llmGlobalSettings.verbose);
|
|
42
32
|
try {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (!config.streamOutput) {
|
|
46
|
-
const progress = new ProgressIndicator('Thinking.');
|
|
47
|
-
try {
|
|
48
|
-
const response = await agent.invoke({ messages }, runConfig);
|
|
49
|
-
output.aiMessage = response.messages[response.messages.length - 1].content;
|
|
50
|
-
const toolNames = response.messages
|
|
51
|
-
.filter((msg) => msg.tool_calls && msg.tool_calls.length > 0)
|
|
52
|
-
.flatMap((msg) => msg.tool_calls?.map((tc) => tc.name)) ?? [];
|
|
53
|
-
if (toolNames.length > 0) {
|
|
54
|
-
displayInfo(`\nUsed tools: ${toolNames.join(', ')}`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
catch (e) {
|
|
58
|
-
displayWarning(`Something went wrong ${e.message}`);
|
|
59
|
-
}
|
|
60
|
-
finally {
|
|
61
|
-
progress.stop();
|
|
62
|
-
}
|
|
63
|
-
display(output.aiMessage);
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
const stream = await agent.stream({ messages }, { ...runConfig, streamMode: 'messages' });
|
|
67
|
-
for await (const [chunk, _metadata] of stream) {
|
|
68
|
-
if (isAIMessage(chunk)) {
|
|
69
|
-
stdout.write(chunk.content, 'utf-8');
|
|
70
|
-
output.aiMessage += chunk.content;
|
|
71
|
-
let toolCalls = chunk.tool_calls;
|
|
72
|
-
if (toolCalls && toolCalls.length > 0) {
|
|
73
|
-
const suffix = toolCalls.length > 1 ? 's' : '';
|
|
74
|
-
const toolCallsString = toolCalls.map((t) => t?.name).join(', ');
|
|
75
|
-
displayInfo(`Using tool${suffix} ${toolCallsString}`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return output.aiMessage;
|
|
81
|
-
}
|
|
82
|
-
catch (error) {
|
|
83
|
-
if (error instanceof Error) {
|
|
84
|
-
if (error?.name === 'ToolException') {
|
|
85
|
-
displayError(`Tool execution failed: ${error.message}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
throw error;
|
|
33
|
+
await invocation.init(command, config, checkpointSaver);
|
|
34
|
+
return await invocation.invoke(messages, runConfig);
|
|
89
35
|
}
|
|
90
36
|
finally {
|
|
91
|
-
|
|
92
|
-
await client.close();
|
|
93
|
-
}
|
|
37
|
+
await invocation.cleanup();
|
|
94
38
|
}
|
|
95
39
|
}
|
|
96
40
|
export function setVerbose(debug) {
|
|
97
41
|
llmGlobalSettings.verbose = debug;
|
|
98
42
|
}
|
|
99
|
-
function filterTools(tools, filesystemConfig) {
|
|
100
|
-
if (filesystemConfig === 'all' || !Array.isArray(filesystemConfig)) {
|
|
101
|
-
return tools;
|
|
102
|
-
}
|
|
103
|
-
// Create set of allowed tool names with mcp__filesystem__ prefix
|
|
104
|
-
const allowedToolNames = new Set(filesystemConfig.map((shortName) => `mcp__filesystem__${shortName}`));
|
|
105
|
-
return tools.filter((tool) => {
|
|
106
|
-
// Allow non-filesystem tools and only allowed filesystem tools
|
|
107
|
-
return !tool.name.startsWith('mcp__filesystem__') || allowedToolNames.has(tool.name);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
function getClient(config) {
|
|
111
|
-
const defaultServers = {};
|
|
112
|
-
// Add filesystem server if configured
|
|
113
|
-
if (config.filesystem && config.filesystem !== 'none') {
|
|
114
|
-
const filesystemConfig = {
|
|
115
|
-
transport: 'stdio',
|
|
116
|
-
command: 'npx',
|
|
117
|
-
args: ['-y', '@modelcontextprotocol/server-filesystem', getCurrentDir()],
|
|
118
|
-
};
|
|
119
|
-
defaultServers.filesystem = filesystemConfig;
|
|
120
|
-
}
|
|
121
|
-
// Merge with user's mcpServers
|
|
122
|
-
const mcpServers = { ...defaultServers, ...(config.mcpServers || {}) };
|
|
123
|
-
// If user provided their own filesystem config, it overrides default
|
|
124
|
-
if (config.mcpServers?.filesystem) {
|
|
125
|
-
mcpServers.filesystem = config.mcpServers.filesystem;
|
|
126
|
-
}
|
|
127
|
-
if (Object.keys(mcpServers).length > 0) {
|
|
128
|
-
return new MultiServerMCPClient({
|
|
129
|
-
throwOnLoadError: true,
|
|
130
|
-
prefixToolNameWithServerName: true,
|
|
131
|
-
additionalToolNamePrefix: 'mcp',
|
|
132
|
-
mcpServers,
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
43
|
//# sourceMappingURL=llmUtils.js.map
|
package/dist/llmUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llmUtils.js","sourceRoot":"","sources":["../src/llmUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"llmUtils.js","sourceRoot":"","sources":["../src/llmUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAG7C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,MAAM,iBAAiB,GAAG;IACxB,OAAO,EAAE,KAAK;CACf,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,OAA8D,EAC9D,QAAmB,EACnB,MAAmB,EACnB,SAA0B,EAC1B,eAAiD;IAEjD,MAAM,YAAY,GAAG,CAAC,KAAkB,EAAE,OAAe,EAAE,EAAE;QAC3D,QAAQ,KAAK,EAAE,CAAC;YACd,KAAK,SAAS;gBACZ,OAAO,CAAC,OAAO,CAAC,CAAC;gBACjB,MAAM;YACR,KAAK,MAAM;gBACT,WAAW,CAAC,OAAO,CAAC,CAAC;gBACrB,MAAM;YACR,KAAK,SAAS;gBACZ,cAAc,CAAC,OAAO,CAAC,CAAC;gBACxB,MAAM;YACR,KAAK,OAAO;gBACV,YAAY,CAAC,OAAO,CAAC,CAAC;gBACtB,MAAM;YACR,KAAK,QAAQ;gBACX,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC/B,MAAM;YACR;gBACE,OAAO,CAAC,OAAO,CAAC,CAAC;gBACjB,MAAM;QACV,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC;IAChD,UAAU,CAAC,UAAU,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;QACxD,OAAO,MAAM,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACtD,CAAC;YAAS,CAAC;QACT,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,iBAAiB,CAAC,OAAO,GAAG,KAAK,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface SessionConfig {
|
|
2
|
+
mode: 'chat' | 'code';
|
|
3
|
+
readModePrompt: () => string | null;
|
|
4
|
+
description: string;
|
|
5
|
+
readyMessage: string;
|
|
6
|
+
exitMessage: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function createInteractiveSession(sessionConfig: SessionConfig, message?: string): Promise<void>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { initConfig } from '#src/config.js';
|
|
2
|
+
import { defaultStatusCallbacks, display } from '#src/consoleUtils.js';
|
|
3
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { MemorySaver } from '@langchain/langgraph';
|
|
6
|
+
import { HumanMessage, SystemMessage } from '@langchain/core/messages';
|
|
7
|
+
import { createInterface, error, exit, stdin as input, stdout as output, } from '#src/systemUtils.js';
|
|
8
|
+
import { getGslothFilePath } from '#src/filePathUtils.js';
|
|
9
|
+
import { appendToFile, generateStandardFileName } from '#src/utils.js';
|
|
10
|
+
import { readBackstory, readGuidelines, readSystemPrompt } from '#src/prompt.js';
|
|
11
|
+
import { Invocation } from '#src/core/Invocation.js';
|
|
12
|
+
export async function createInteractiveSession(sessionConfig, message) {
|
|
13
|
+
const config = { ...(await initConfig()), streamOutput: false };
|
|
14
|
+
const checkpointSaver = new MemorySaver();
|
|
15
|
+
// Initialize Invocation once
|
|
16
|
+
const invocation = new Invocation(defaultStatusCallbacks);
|
|
17
|
+
await invocation.init(sessionConfig.mode, config, checkpointSaver);
|
|
18
|
+
try {
|
|
19
|
+
const rl = createInterface({ input, output });
|
|
20
|
+
let isFirstMessage = true;
|
|
21
|
+
let shouldExit = false;
|
|
22
|
+
const thread_id = uuidv4();
|
|
23
|
+
const logFileName = getGslothFilePath(generateStandardFileName(sessionConfig.mode.toUpperCase()));
|
|
24
|
+
display(chalk.gray(`${sessionConfig.mode} session will be logged to ${logFileName}\n`));
|
|
25
|
+
const processMessage = async (userInput) => {
|
|
26
|
+
const messages = [];
|
|
27
|
+
if (isFirstMessage) {
|
|
28
|
+
const systemPromptParts = [readBackstory(), readGuidelines(config.projectGuidelines)];
|
|
29
|
+
const modePrompt = sessionConfig.readModePrompt();
|
|
30
|
+
if (modePrompt) {
|
|
31
|
+
systemPromptParts.push(modePrompt);
|
|
32
|
+
}
|
|
33
|
+
const systemPrompt = readSystemPrompt();
|
|
34
|
+
if (systemPrompt) {
|
|
35
|
+
systemPromptParts.push(systemPrompt);
|
|
36
|
+
}
|
|
37
|
+
messages.push(new SystemMessage(systemPromptParts.join('\n')));
|
|
38
|
+
}
|
|
39
|
+
messages.push(new HumanMessage(userInput));
|
|
40
|
+
const runConfig = {
|
|
41
|
+
configurable: { thread_id },
|
|
42
|
+
};
|
|
43
|
+
const aiResponse = await invocation.invoke(messages, runConfig);
|
|
44
|
+
const logEntry = `## User\n\n${userInput}\n\n## Assistant\n\n${aiResponse}\n\n`;
|
|
45
|
+
appendToFile(logFileName, logEntry);
|
|
46
|
+
isFirstMessage = false;
|
|
47
|
+
};
|
|
48
|
+
const askQuestion = () => {
|
|
49
|
+
rl.question(chalk.magenta(' > '), async (userInput) => {
|
|
50
|
+
if (!userInput.trim()) {
|
|
51
|
+
rl.close(); // This is not the end of the loop, simply skipping inference if no input
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (userInput.toLowerCase() === 'exit') {
|
|
55
|
+
rl.close();
|
|
56
|
+
shouldExit = true;
|
|
57
|
+
await invocation.cleanup();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
await processMessage(userInput);
|
|
61
|
+
display(chalk.gray(sessionConfig.exitMessage));
|
|
62
|
+
if (!shouldExit)
|
|
63
|
+
askQuestion();
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
if (message) {
|
|
67
|
+
await processMessage(message);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
display(sessionConfig.readyMessage);
|
|
71
|
+
display(chalk.gray(sessionConfig.exitMessage));
|
|
72
|
+
}
|
|
73
|
+
if (!shouldExit)
|
|
74
|
+
askQuestion();
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
await invocation.cleanup();
|
|
78
|
+
error(`Error in ${sessionConfig.mode} command: ${err}`);
|
|
79
|
+
exit(1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=interactiveSessionModule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactiveSessionModule.js","sourceRoot":"","sources":["../../src/modules/interactiveSessionModule.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/modules/types.d.ts
CHANGED
|
File without changes
|
package/dist/modules/types.js
CHANGED
|
File without changes
|
|
File without changes
|
package/dist/prompt.d.ts
CHANGED
|
File without changes
|
package/dist/prompt.js
CHANGED
|
File without changes
|
package/dist/prompt.js.map
CHANGED
|
File without changes
|
package/dist/providers/file.d.ts
CHANGED
|
File without changes
|
package/dist/providers/file.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/providers/text.d.ts
CHANGED
|
File without changes
|
package/dist/providers/text.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/providers/types.js
CHANGED
|
File without changes
|
|
File without changes
|
package/dist/systemUtils.d.ts
CHANGED
|
File without changes
|
package/dist/systemUtils.js
CHANGED
|
File without changes
|
package/dist/systemUtils.js.map
CHANGED
|
File without changes
|
package/dist/utils.d.ts
CHANGED
|
File without changes
|
package/dist/utils.js
CHANGED
|
File without changes
|
package/dist/utils.js.map
CHANGED
|
File without changes
|
package/docs/COMMANDS.md
CHANGED
|
File without changes
|
package/docs/CONFIGURATION.md
CHANGED
|
File without changes
|
package/docs/DEVELOPMENT.md
CHANGED
|
File without changes
|
package/docs/RELEASE-HOWTO.md
CHANGED
|
File without changes
|
package/eslint.config.js
CHANGED
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gaunt-sloth-assistant",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Andrew Kondratev",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@eslint/js": "^9.26.0",
|
|
42
|
-
"@types/node": "^
|
|
42
|
+
"@types/node": "^24.0.2",
|
|
43
43
|
"@types/uuid": "^10.0.0",
|
|
44
44
|
"@typescript-eslint/eslint-plugin": "^8.34.0",
|
|
45
45
|
"@typescript-eslint/parser": "^8.34.0",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Refactor to facilitate imports
|
|
2
|
+
|
|
3
|
+
We need to conduct refactoring, so we can use parts of Gaunt Sloth from other projects.
|
|
4
|
+
|
|
5
|
+
The gaunt sloth project is pretty small, so there's probably no reason to split it into packages with workspaces, so we just want to make the code structure more meaningful and easier to reuse.
|
|
6
|
+
|
|
7
|
+
## Commands
|
|
8
|
+
|
|
9
|
+
in `commands` (dir already exists)
|
|
10
|
+
|
|
11
|
+
These are commander commands, their behaviour should remain unchanged
|
|
12
|
+
|
|
13
|
+
- askCommand.ts - questionAnsweringModule
|
|
14
|
+
- chatCommand.ts - chatModule
|
|
15
|
+
- codeCommand.ts - chatModule
|
|
16
|
+
- initCommand.ts - (keep this unchanged)
|
|
17
|
+
- prCommand.ts - reviewModule
|
|
18
|
+
- reviewCommand.ts - reviewModule
|
|
19
|
+
|
|
20
|
+
## Modules
|
|
21
|
+
|
|
22
|
+
in `modules` (dir already exists)
|
|
23
|
+
|
|
24
|
+
These are modules which can do I/O operations such as reading configurations, prompts from filesystem.
|
|
25
|
+
|
|
26
|
+
- questionAnsweringModule
|
|
27
|
+
- reviewModule
|
|
28
|
+
- chatModule
|
|
29
|
+
|
|
30
|
+
## Core functions
|
|
31
|
+
|
|
32
|
+
Core functions should not deal with I/O and configurations themselves, but should rather accept values via arguments, consume values from provided supplier functions, set values to consumers and return values, with favour of plain arguments and returns.
|
|
33
|
+
|
|
34
|
+
in `core` (new dir)
|
|
35
|
+
|
|
36
|
+
- answer
|
|
37
|
+
- review
|
|
38
|
+
- chat
|
|
39
|
+
|
|
40
|
+
## Plan
|
|
41
|
+
- Read .gsloth.guidelines.md
|
|
42
|
+
- Implement changes
|
|
43
|
+
- Read "Testing" section of .gsloth.guidelines.md
|
|
44
|
+
- Update tests
|
|
45
|
+
- lint
|
|
46
|
+
- Iterate with tests and lint
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Invocation class
|
|
2
|
+
|
|
3
|
+
We need to refactor invocation, but let's keep `invoke` of `src/llmUtils.ts` unchanged.
|
|
4
|
+
|
|
5
|
+
## Invocation class
|
|
6
|
+
We need to create the `Invocation` class in src/core, all the llmUtils code should end up there.
|
|
7
|
+
|
|
8
|
+
### No direct I/O in Invocation class4
|
|
9
|
+
Class constructor should take callback `statusUpdate` with two parameters, level and message,
|
|
10
|
+
this callback will call all these `display`, `displayWarning`, etc.
|
|
11
|
+
The callback should have special level to replace `stdout.write(chunk.content as string, 'utf-8');`
|
|
12
|
+
|
|
13
|
+
### invoke method
|
|
14
|
+
The class should have the `invoke` method, which should do core invocation but should not
|
|
15
|
+
create agent or close mcpClient.
|
|
16
|
+
|
|
17
|
+
## Plan
|
|
18
|
+
- Read .gsloth.guidelines.md
|
|
19
|
+
- Implement change
|
|
20
|
+
- Read the "Testing" section of .gsloth.guidelines.md
|
|
21
|
+
- run tests and update them if necessary
|
|
22
|
+
- run and fix lint
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
File without changes
|
|
@@ -1,22 +1,6 @@
|
|
|
1
|
-
import { initConfig } from '#src/config.js';
|
|
2
|
-
import { display } from '#src/consoleUtils.js';
|
|
3
|
-
import { invoke } from '#src/llmUtils.js';
|
|
4
1
|
import { Command } from 'commander';
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import { MemorySaver } from '@langchain/langgraph';
|
|
8
|
-
import { HumanMessage, SystemMessage, type BaseMessage } from '@langchain/core/messages';
|
|
9
|
-
import {
|
|
10
|
-
createInterface,
|
|
11
|
-
error,
|
|
12
|
-
exit,
|
|
13
|
-
stdin as input,
|
|
14
|
-
stdout as output,
|
|
15
|
-
} from '#src/systemUtils.js';
|
|
16
|
-
import { RunnableConfig } from '@langchain/core/runnables';
|
|
17
|
-
import { getGslothFilePath } from '#src/filePathUtils.js';
|
|
18
|
-
import { generateStandardFileName, appendToFile } from '#src/utils.js';
|
|
19
|
-
import { readBackstory, readGuidelines, readSystemPrompt, readChatPrompt } from '#src/prompt.js';
|
|
2
|
+
import { createInteractiveSession, SessionConfig } from '#src/modules/interactiveSessionModule.js';
|
|
3
|
+
import { readChatPrompt } from '#src/prompt.js';
|
|
20
4
|
|
|
21
5
|
export function chatCommand(program: Command) {
|
|
22
6
|
program
|
|
@@ -24,77 +8,14 @@ export function chatCommand(program: Command) {
|
|
|
24
8
|
.description('Start an interactive chat session with Gaunt Sloth')
|
|
25
9
|
.argument('[message]', 'Initial message to start the chat')
|
|
26
10
|
.action(async (message: string) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
display(chalk.gray(`Chat session will be logged to ${chatLogFileName}\n`));
|
|
38
|
-
|
|
39
|
-
const processMessage = async (userInput: string) => {
|
|
40
|
-
const messages: BaseMessage[] = [];
|
|
41
|
-
if (isFirstMessage) {
|
|
42
|
-
const systemPromptParts = [readBackstory(), readGuidelines(config.projectGuidelines)];
|
|
43
|
-
const chatPrompt = readChatPrompt();
|
|
44
|
-
if (chatPrompt) {
|
|
45
|
-
systemPromptParts.push(chatPrompt);
|
|
46
|
-
}
|
|
47
|
-
const systemPrompt = readSystemPrompt();
|
|
48
|
-
if (systemPrompt) {
|
|
49
|
-
systemPromptParts.push(systemPrompt);
|
|
50
|
-
}
|
|
51
|
-
messages.push(new SystemMessage(systemPromptParts.join('\n')));
|
|
52
|
-
}
|
|
53
|
-
messages.push(new HumanMessage(userInput));
|
|
54
|
-
|
|
55
|
-
const runConfig = {
|
|
56
|
-
configurable: { thread_id },
|
|
57
|
-
} as RunnableConfig;
|
|
58
|
-
|
|
59
|
-
const aiResponse = await invoke('chat', messages, config, runConfig, checkpointSaver);
|
|
60
|
-
|
|
61
|
-
const logEntry = `## User\n\n${userInput}\n\n## Assistant\n\n${aiResponse}\n\n`;
|
|
62
|
-
appendToFile(chatLogFileName, logEntry);
|
|
63
|
-
|
|
64
|
-
isFirstMessage = false;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const askQuestion = () => {
|
|
68
|
-
rl.question(chalk.magenta(' > '), async (userInput) => {
|
|
69
|
-
if (userInput.toLowerCase() === 'exit') {
|
|
70
|
-
rl.close();
|
|
71
|
-
shouldExit = true;
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (isFirstMessage && !userInput.trim()) {
|
|
75
|
-
rl.close();
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
if (!userInput.trim()) {
|
|
79
|
-
rl.close();
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
await processMessage(userInput);
|
|
83
|
-
display(chalk.gray("Type 'exit' or hit Ctrl+C to exit chat\n"));
|
|
84
|
-
if (!shouldExit) askQuestion();
|
|
85
|
-
});
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
if (message) {
|
|
89
|
-
await processMessage(message);
|
|
90
|
-
} else {
|
|
91
|
-
display('\nGaunt Sloth is ready to chat. Type your prompt.');
|
|
92
|
-
display(chalk.gray("Type 'exit' or hit Ctrl+C to exit chat\n"));
|
|
93
|
-
}
|
|
94
|
-
if (!shouldExit) askQuestion();
|
|
95
|
-
} catch (err) {
|
|
96
|
-
error(`Error in chat command: ${err}`);
|
|
97
|
-
exit(1);
|
|
98
|
-
}
|
|
11
|
+
const sessionConfig: SessionConfig = {
|
|
12
|
+
mode: 'chat',
|
|
13
|
+
readModePrompt: readChatPrompt,
|
|
14
|
+
description: 'Start an interactive chat session with Gaunt Sloth',
|
|
15
|
+
readyMessage: '\nGaunt Sloth is ready to chat. Type your prompt.',
|
|
16
|
+
exitMessage: "Type 'exit' or hit Ctrl+C to exit chat\n",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
await createInteractiveSession(sessionConfig, message);
|
|
99
20
|
});
|
|
100
21
|
}
|