Skip to content

Commit 01cfce4

Browse files
committed
fix: refine UX messages
1 parent efc7fe1 commit 01cfce4

File tree

5 files changed

+25
-91
lines changed

5 files changed

+25
-91
lines changed

chat-client/src/client/features/rules.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export class RulesList {
8282
// Close the rules list first
8383
this.rulesList?.close()
8484

85-
// Use the current tab I, the tabId should be the same as the one used for the rules list
85+
// Use the current tab, the tabId should be the same as the one used for the rules list
8686
this.messager.onChatPrompt({
8787
prompt: {
8888
prompt: 'Generate a Memory Bank for this project',
@@ -175,13 +175,11 @@ const createRuleListItem: DetailedListItem = {
175175
}
176176

177177
function createMemoryBankListItem(rules: RulesFolder[]): DetailedListItem {
178-
// Handles text changes between "Generation" and "Regenerate"
178+
// Handles button text changes between "Generation" and "Regenerate"
179179
const memoryBankFiles = ['product', 'structure', 'tech', 'guidelines']
180180

181-
// Find memory-bank folder
182181
const memoryBankFolder = rules.find(folder => folder.folderName === 'memory-bank')
183182

184-
// Check if any memory bank files exist
185183
const hasMemoryBankFiles =
186184
memoryBankFolder && memoryBankFolder.rules.some(rule => memoryBankFiles.includes(rule.name))
187185

server/aws-lsp-codewhisperer/src/language-server/agenticChat/agenticChatController.ts

Lines changed: 11 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -476,17 +476,10 @@ export class AgenticChatController implements ChatHandlers {
476476
await this.#features.workspace.fs.writeFile(input.path, toolUse.fileChange.before)
477477
} else {
478478
await this.#features.workspace.fs.rm(input.path)
479-
void LocalProjectContextController.getInstance()
480-
.then(controller => {
481-
const filePath = URI.file(input.path).fsPath
482-
return controller.updateIndexAndContextCommand([filePath], false)
483-
})
484-
.catch(error => {
485-
// Log the error but don't let it crash the server
486-
this.#features.logging.warn(
487-
`Failed to update project context for deleted file ${input.path}: ${error.message}`
488-
)
489-
})
479+
void LocalProjectContextController.getInstance().then(controller => {
480+
const filePath = URI.file(input.path).fsPath
481+
return controller.updateIndexAndContextCommand([filePath], false)
482+
})
490483
}
491484
}
492485

@@ -863,44 +856,17 @@ export class AgenticChatController implements ChatHandlers {
863856
const actionType = memoryBankExists ? 'Regenerating' : 'Generating'
864857
this.#features.logging.info(`${actionType} Memory Bank for workspace: ${workspaceUri}`)
865858

866-
// Send initial status message
867-
try {
868-
await this.#features.chat.sendChatUpdate({
869-
tabId: params.tabId,
870-
data: {
871-
messages: [
872-
{
873-
messageId: `memory-bank-init-${Date.now()}`,
874-
body: `**${actionType} Memory Bank**\n\n${memoryBankExists ? 'Updating existing' : 'Generating new'} Memory Bank for your workspace.`,
875-
},
876-
],
877-
},
878-
})
879-
} catch (updateError) {
880-
this.#features.logging.warn(`Failed to send initial status update: ${updateError}`)
881-
}
859+
const resultStream = this.#getChatResultStream(params.partialResultToken)
860+
await resultStream.writeResultBlock({
861+
body: `Preparing to analyze your project...`,
862+
type: 'answer',
863+
messageId: crypto.randomUUID(),
864+
})
882865

883866
const comprehensivePrompt = await this.#memoryBankController.prepareComprehensiveMemoryBankPrompt(
884867
workspaceUri,
885-
async (message: string) => {
886-
try {
887-
await this.#features.chat.sendChatUpdate({
888-
tabId: params.tabId,
889-
data: {
890-
messages: [
891-
{
892-
messageId: `memory-bank-status-${Date.now()}`,
893-
body: message,
894-
},
895-
],
896-
},
897-
})
898-
} catch (updateError) {
899-
this.#features.logging.warn(`Failed to send status update: ${updateError}`)
900-
}
901-
},
902868
async (prompt: string) => {
903-
// Direct LLM call for ranking - no agentic loop, just a simple API call
869+
// Direct LLM call for ranking - no agentic loop
904870
try {
905871
if (!this.#serviceManager) {
906872
throw new Error('amazonQServiceManager is not initialized')
@@ -920,16 +886,13 @@ export class AgenticChatController implements ChatHandlers {
920886

921887
const response = await client.sendMessage(requestInput)
922888

923-
// Extract response with size limit to prevent memory issues
924889
let responseContent = ''
925890
const maxResponseSize = 50000 // 50KB limit
926891

927892
if (response.sendMessageResponse) {
928893
for await (const chatEvent of response.sendMessageResponse) {
929894
if (chatEvent.assistantResponseEvent?.content) {
930895
responseContent += chatEvent.assistantResponseEvent.content
931-
932-
// Prevent unbounded memory growth
933896
if (responseContent.length > maxResponseSize) {
934897
this.#features.logging.warn('LLM response exceeded size limit, truncating')
935898
break
@@ -1342,7 +1305,6 @@ export class AgenticChatController implements ChatHandlers {
13421305
}),
13431306
chatResultStream,
13441307
session,
1345-
tabId,
13461308
documentReference,
13471309
true
13481310
)
@@ -1475,7 +1437,6 @@ export class AgenticChatController implements ChatHandlers {
14751437
this.#debug(
14761438
`generateAssistantResponse/SendMessage Request: ${JSON.stringify(currentRequestInput, this.#imageReplacer, 2)}`
14771439
)
1478-
14791440
const response = await session.getChatResponse(currentRequestInput)
14801441
if (response.$metadata.requestId) {
14811442
metric.mergeWith({
@@ -1517,7 +1478,6 @@ export class AgenticChatController implements ChatHandlers {
15171478
}),
15181479
chatResultStream,
15191480
session,
1520-
tabId,
15211481
documentReference
15221482
)
15231483
const llmLatency = Date.now() - this.#llmRequestStartTime
@@ -4333,7 +4293,6 @@ export class AgenticChatController implements ChatHandlers {
43334293
metric: Metric<AddMessageEvent>,
43344294
chatResultStream: AgenticChatResultStream,
43354295
session: ChatSessionService,
4336-
tabId: string,
43374296
contextList?: FileList,
43384297
isCompaction?: boolean
43394298
): Promise<Result<AgenticChatResultWithMetadata, string>> {
@@ -4357,7 +4316,6 @@ export class AgenticChatController implements ChatHandlers {
43574316
chatResultStream,
43584317
streamWriter,
43594318
session,
4360-
tabId,
43614319
contextList,
43624320
abortController.signal,
43634321
isCompaction
@@ -4437,7 +4395,6 @@ export class AgenticChatController implements ChatHandlers {
44374395
chatResultStream: AgenticChatResultStream,
44384396
streamWriter: ResultStreamWriter,
44394397
session: ChatSessionService,
4440-
tabId: string,
44414398
contextList?: FileList,
44424399
abortSignal?: AbortSignal,
44434400
isCompaction?: boolean

server/aws-lsp-codewhisperer/src/language-server/agenticChat/context/additionalContextProvider.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,22 +157,19 @@ export class AdditionalContextProvider {
157157
if (memoryBankFiles.length > 0) {
158158
let needsUpdate = false
159159

160-
// Ensure memory-bank folder is active by default
161160
const memoryBankFolderName = 'memory-bank'
162161
if (rulesState.folders[memoryBankFolderName] === undefined) {
163162
rulesState.folders[memoryBankFolderName] = true
164163
needsUpdate = true
165164
}
166165

167-
// Ensure each memory bank file is active by default
168166
memoryBankFiles.forEach(file => {
169167
if (rulesState.rules[file.id] === undefined) {
170168
rulesState.rules[file.id] = true
171169
needsUpdate = true
172170
}
173171
})
174172

175-
// Save the updated rules state if we made changes
176173
if (needsUpdate) {
177174
this.chatDb.setRules(tabId, rulesState)
178175
this.features.logging.info(`Memory Bank files activated by default: ${memoryBankFiles.length} files`)
@@ -734,7 +731,6 @@ export class AdditionalContextProvider {
734731
if (dirPath === '.amazonq/rules/memory-bank') {
735732
folderName = 'memory-bank'
736733
} else {
737-
// Use the full directory path for folder name
738734
folderName = dirPath
739735
}
740736
}

server/aws-lsp-codewhisperer/src/language-server/agenticChat/context/memorybank/memoryBankController.ts

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ export class MemoryBankController {
2323

2424
constructor(private features: Features) {}
2525

26-
/**
27-
* Get singleton instance of MemoryBankController
28-
*/
2926
static getInstance(features: Features): MemoryBankController {
3027
if (!MemoryBankController.instance) {
3128
MemoryBankController.instance = new MemoryBankController(features)
@@ -35,6 +32,7 @@ export class MemoryBankController {
3532

3633
/**
3734
* Check if a prompt is requesting memory bank creation
35+
* Can be expanded based on feedbacks
3836
*/
3937
isMemoryBankCreationRequest(prompt: string): boolean {
4038
const normalizedPrompt = prompt.toLowerCase().trim()
@@ -59,32 +57,21 @@ export class MemoryBankController {
5957
*/
6058
async prepareComprehensiveMemoryBankPrompt(
6159
workspaceFolderUri: string,
62-
statusUpdateFunction: (message: string) => Promise<void>,
6360
llmCallFunction: (prompt: string) => Promise<string>
6461
): Promise<string> {
6562
try {
6663
// Step 1: Clean directory
6764
await this.cleanMemoryBankDirectory(workspaceFolderUri)
6865

69-
// Step 2: Send status update
70-
await statusUpdateFunction(
71-
'**Analyzing codebase structure...**\n\nScanning files and calculating similarity metrics.'
72-
)
73-
74-
// Step 3: Execute deterministic analysis (TF-IDF)
66+
// Step 2: Execute deterministic analysis (TF-IDF)
7567
this.features.logging.info(`Memory Bank: running analysis for workspace: ${workspaceFolderUri}`)
7668
const analysisResults = await this.executeGuidelinesGenerationPipeline(workspaceFolderUri)
7769

78-
// Step 4: Send ranking status update
79-
await statusUpdateFunction(
80-
'**Ranking important files...**\n\nUsing AI to identify the most representative files.'
81-
)
82-
83-
// Step 5: Make LLM call for file ranking
70+
// Step 3: Make LLM call for file ranking
8471
const rankingPrompt = MemoryBankPrompts.getFileRankingPrompt(analysisResults.formattedFilesString, 20)
8572
const rankedFilesResponse = await llmCallFunction(rankingPrompt)
8673

87-
// Step 6: Parse ranked files
74+
// Step 4: Parse ranked files
8875
let rankedFilesList: string[] = []
8976
try {
9077
// Clean the response - remove any markdown formatting or extra text
@@ -128,13 +115,7 @@ export class MemoryBankController {
128115
`Memory Bank: using ${rankedFilesList.length} files for documentation generation`
129116
)
130117

131-
// Step 7: Send final status update
132-
const totalChunks = Math.ceil(rankedFilesList.length / 4)
133-
await statusUpdateFunction(
134-
`**Generating comprehensive documentation...**\n\nGenerating all 4 Memory Bank files with iterative analysis.\n\n**Agent Processing:** Processes ${rankedFilesList.length} files in chunks of 4\n${Array.from({ length: totalChunks }, (_, i) => `- Iteration ${i + 1}: Files ${i * 4 + 1}-${Math.min((i + 1) * 4, rankedFilesList.length)} (${Math.min(4, rankedFilesList.length - i * 4)} files)`).join('\n')}\n↓`
135-
)
136-
137-
// Step 8: Create the comprehensive prompt with ranked files
118+
// Step 5: Create the comprehensive prompt with ranked files
138119
const finalPrompt = MemoryBankPrompts.getCompleteMemoryBankPrompt(rankedFilesList)
139120
return finalPrompt
140121
} catch (error) {
@@ -144,7 +125,7 @@ export class MemoryBankController {
144125
}
145126

146127
/**
147-
* Clean memory bank directory
128+
* Clean and recreate memory bank directory
148129
*/
149130
async cleanMemoryBankDirectory(workspaceFolderUri: string): Promise<void> {
150131
try {
@@ -180,7 +161,7 @@ export class MemoryBankController {
180161
}
181162

182163
/**
183-
* SCIENCE DOCUMENT METHOD 1: file discovery (OPTIMIZED)
164+
* files discovery
184165
*/
185166
async discoverAllSourceFiles(
186167
workspaceFolderUri: string,
@@ -213,7 +194,7 @@ export class MemoryBankController {
213194
}
214195

215196
/**
216-
* SCIENCE DOCUMENT METHOD 2: line counting
197+
* line counting
217198
*/
218199
async calculateFileLineCount(filePath: string): Promise<number> {
219200
try {
@@ -226,7 +207,7 @@ export class MemoryBankController {
226207
}
227208

228209
/**
229-
* SCIENCE DOCUMENT METHOD 3: lexical dissimilarity calculation (OPTIMIZED)
210+
* lexical dissimilarity calculation
230211
*/
231212
async calculateLexicalDissimilarity(
232213
files: Array<{ path: string; size: number }>

server/aws-lsp-codewhisperer/src/language-server/agenticChat/context/memorybank/memoryBankPrompts.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ The .amazonq/rules/memory-bank/ directory has been prepared and cleaned. You can
6767
6868
**Part 1: Fresh Analysis and Documentation Creation**
6969
70-
FIRST: Start by saying "I'll analyze the codebase and generate a complete Memory Bank. Let me start by exploring the project structure."
70+
FIRST: Start by saying "Now I'll explore the project structure and create the Memory Bank documentation."
7171
7272
THEN: Explore the project structure and create these files (send progress message before each):
7373
@@ -88,6 +88,8 @@ THEN: Explore the project structure and create these files (send progress messag
8888
8989
**Part 2: Advanced Guidelines Generation Using Iterative Analysis**
9090
91+
THEN: Say "Now I'll analyze the most representative files from the codebase to identify development patterns and create comprehensive guidelines."
92+
9193
I have ${rankedFiles.length} representative files ranked by lexical dissimilarity analysis:
9294
${rankedFiles.map((file, i) => `${i + 1}. ${file}`).join('\n')}
9395

0 commit comments

Comments
 (0)