@aws/lsp-codewhisperer 0.0.82 → 0.0.84

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 (135) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/out/language-server/agenticChat/agenticChatController.js +105 -35
  3. package/out/language-server/agenticChat/agenticChatController.js.map +1 -1
  4. package/out/language-server/agenticChat/agenticChatResultStream.d.ts +1 -0
  5. package/out/language-server/agenticChat/agenticChatResultStream.js +21 -0
  6. package/out/language-server/agenticChat/agenticChatResultStream.js.map +1 -1
  7. package/out/language-server/agenticChat/constants/constants.d.ts +30 -0
  8. package/out/language-server/agenticChat/constants/constants.js +44 -1
  9. package/out/language-server/agenticChat/constants/constants.js.map +1 -1
  10. package/out/language-server/agenticChat/constants/modelSelection.d.ts +2 -2
  11. package/out/language-server/agenticChat/constants/modelSelection.js +6 -5
  12. package/out/language-server/agenticChat/constants/modelSelection.js.map +1 -1
  13. package/out/language-server/agenticChat/context/agenticChatTriggerContext.d.ts +2 -1
  14. package/out/language-server/agenticChat/context/agenticChatTriggerContext.js +3 -1
  15. package/out/language-server/agenticChat/context/agenticChatTriggerContext.js.map +1 -1
  16. package/out/language-server/agenticChat/context/memorybank/memoryBankController.js +4 -3
  17. package/out/language-server/agenticChat/context/memorybank/memoryBankController.js.map +1 -1
  18. package/out/language-server/agenticChat/retry/delayInterceptor.d.ts +33 -0
  19. package/out/language-server/agenticChat/retry/delayInterceptor.js +79 -0
  20. package/out/language-server/agenticChat/retry/delayInterceptor.js.map +1 -0
  21. package/out/language-server/agenticChat/retry/errorTransformer.d.ts +15 -0
  22. package/out/language-server/agenticChat/retry/errorTransformer.js +152 -0
  23. package/out/language-server/agenticChat/retry/errorTransformer.js.map +1 -0
  24. package/out/language-server/agenticChat/retry/index.d.ts +3 -0
  25. package/out/language-server/agenticChat/retry/index.js +11 -0
  26. package/out/language-server/agenticChat/retry/index.js.map +1 -0
  27. package/out/language-server/agenticChat/retry/qRetryStrategy.d.ts +20 -0
  28. package/out/language-server/agenticChat/retry/qRetryStrategy.js +71 -0
  29. package/out/language-server/agenticChat/retry/qRetryStrategy.js.map +1 -0
  30. package/out/language-server/agenticChat/retry/retryClassifier.d.ts +32 -0
  31. package/out/language-server/agenticChat/retry/retryClassifier.js +122 -0
  32. package/out/language-server/agenticChat/retry/retryClassifier.js.map +1 -0
  33. package/out/language-server/agenticChat/tabBarController.d.ts +4 -0
  34. package/out/language-server/agenticChat/tabBarController.js +19 -2
  35. package/out/language-server/agenticChat/tabBarController.js.map +1 -1
  36. package/out/language-server/agenticChat/tools/chatDb/chatDb.d.ts +3 -25
  37. package/out/language-server/agenticChat/tools/chatDb/chatDb.js +12 -107
  38. package/out/language-server/agenticChat/tools/chatDb/chatDb.js.map +1 -1
  39. package/out/language-server/agenticChat/tools/chatDb/util.js +1 -2
  40. package/out/language-server/agenticChat/tools/chatDb/util.js.map +1 -1
  41. package/out/language-server/agenticChat/tools/fsRead.d.ts +3 -1
  42. package/out/language-server/agenticChat/tools/fsRead.js +12 -7
  43. package/out/language-server/agenticChat/tools/fsRead.js.map +1 -1
  44. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.js +30 -14
  45. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.js.map +1 -1
  46. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewConstants.js +1 -1
  47. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewConstants.js.map +1 -1
  48. package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewTypes.d.ts +8 -0
  49. package/out/language-server/chat/chatController.js.map +1 -1
  50. package/out/language-server/chat/chatSessionService.d.ts +8 -1
  51. package/out/language-server/chat/chatSessionService.js +38 -81
  52. package/out/language-server/chat/chatSessionService.js.map +1 -1
  53. package/out/language-server/chat/constants.d.ts +1 -0
  54. package/out/language-server/chat/constants.js +2 -1
  55. package/out/language-server/chat/constants.js.map +1 -1
  56. package/out/language-server/chat/telemetry/chatTelemetryController.d.ts +2 -1
  57. package/out/language-server/chat/telemetry/chatTelemetryController.js +12 -1
  58. package/out/language-server/chat/telemetry/chatTelemetryController.js.map +1 -1
  59. package/out/language-server/inline-completion/codeWhispererServer.d.ts +0 -1
  60. package/out/language-server/inline-completion/codeWhispererServer.js +17 -481
  61. package/out/language-server/inline-completion/codeWhispererServer.js.map +1 -1
  62. package/out/language-server/inline-completion/contants/constants.js.map +1 -0
  63. package/out/language-server/inline-completion/{editCompletionHandler.d.ts → handler/editCompletionHandler.d.ts} +10 -10
  64. package/out/language-server/inline-completion/{editCompletionHandler.js → handler/editCompletionHandler.js} +17 -14
  65. package/out/language-server/inline-completion/handler/editCompletionHandler.js.map +1 -0
  66. package/out/language-server/inline-completion/handler/inlineCompletionHandler.d.ts +32 -0
  67. package/out/language-server/inline-completion/handler/inlineCompletionHandler.js +377 -0
  68. package/out/language-server/inline-completion/handler/inlineCompletionHandler.js.map +1 -0
  69. package/out/language-server/inline-completion/handler/sessionResultsHandler.d.ts +23 -0
  70. package/out/language-server/inline-completion/handler/sessionResultsHandler.js +119 -0
  71. package/out/language-server/inline-completion/handler/sessionResultsHandler.js.map +1 -0
  72. package/out/language-server/inline-completion/{telemetry.d.ts → telemetry/telemetry.d.ts} +2 -2
  73. package/out/language-server/inline-completion/{telemetry.js → telemetry/telemetry.js} +2 -2
  74. package/out/language-server/inline-completion/telemetry/telemetry.js.map +1 -0
  75. package/out/language-server/inline-completion/{codeDiffTracker.d.ts → tracker/codeDiffTracker.d.ts} +2 -2
  76. package/out/language-server/inline-completion/{codeDiffTracker.js → tracker/codeDiffTracker.js} +1 -1
  77. package/out/language-server/inline-completion/tracker/codeDiffTracker.js.map +1 -0
  78. package/out/language-server/inline-completion/tracker/codeEditTracker.js +1 -1
  79. package/out/language-server/inline-completion/tracker/codeEditTracker.js.map +1 -1
  80. package/out/language-server/inline-completion/{codePercentage.d.ts → tracker/codePercentageTracker.d.ts} +1 -1
  81. package/out/language-server/inline-completion/{codePercentage.js → tracker/codePercentageTracker.js} +1 -1
  82. package/out/language-server/inline-completion/tracker/codePercentageTracker.js.map +1 -0
  83. package/out/language-server/inline-completion/{diffUtils.d.ts → utils/diffUtils.d.ts} +29 -12
  84. package/out/language-server/inline-completion/utils/diffUtils.js +407 -0
  85. package/out/language-server/inline-completion/utils/diffUtils.js.map +1 -0
  86. package/out/language-server/inline-completion/utils/mergeRightUtils.d.ts +9 -0
  87. package/out/language-server/inline-completion/utils/mergeRightUtils.js +67 -0
  88. package/out/language-server/inline-completion/utils/mergeRightUtils.js.map +1 -0
  89. package/out/language-server/inline-completion/utils/textDocumentUtils.d.ts +3 -0
  90. package/out/language-server/inline-completion/utils/textDocumentUtils.js +37 -0
  91. package/out/language-server/inline-completion/utils/textDocumentUtils.js.map +1 -0
  92. package/out/language-server/inline-completion/{trigger.d.ts → utils/triggerUtils.d.ts} +4 -4
  93. package/out/language-server/inline-completion/{trigger.js → utils/triggerUtils.js} +3 -3
  94. package/out/language-server/inline-completion/utils/triggerUtils.js.map +1 -0
  95. package/out/language-server/netTransform/artifactManager.d.ts +2 -2
  96. package/out/language-server/netTransform/artifactManager.js +6 -10
  97. package/out/language-server/netTransform/artifactManager.js.map +1 -1
  98. package/out/language-server/workspaceContext/workspaceFolderManager.js +3 -1
  99. package/out/language-server/workspaceContext/workspaceFolderManager.js.map +1 -1
  100. package/out/shared/amazonQServiceManager/AmazonQIAMServiceManager.d.ts +1 -1
  101. package/out/shared/amazonQServiceManager/AmazonQIAMServiceManager.js +8 -2
  102. package/out/shared/amazonQServiceManager/AmazonQIAMServiceManager.js.map +1 -1
  103. package/out/shared/amazonQServiceManager/AmazonQTokenServiceManager.js +1 -0
  104. package/out/shared/amazonQServiceManager/AmazonQTokenServiceManager.js.map +1 -1
  105. package/out/shared/amazonQServiceManager/BaseAmazonQServiceManager.js +6 -0
  106. package/out/shared/amazonQServiceManager/BaseAmazonQServiceManager.js.map +1 -1
  107. package/out/shared/codeWhispererService.js +52 -20
  108. package/out/shared/codeWhispererService.js.map +1 -1
  109. package/out/shared/streamingClientService.d.ts +7 -1
  110. package/out/shared/streamingClientService.js +53 -15
  111. package/out/shared/streamingClientService.js.map +1 -1
  112. package/out/shared/telemetry/telemetryService.js.map +1 -1
  113. package/out/shared/telemetry/types.d.ts +8 -0
  114. package/out/shared/telemetry/types.js +1 -0
  115. package/out/shared/telemetry/types.js.map +1 -1
  116. package/out/shared/testUtils.d.ts +0 -3
  117. package/out/shared/testUtils.js +1 -22
  118. package/out/shared/testUtils.js.map +1 -1
  119. package/out/shared/utils.d.ts +10 -4
  120. package/out/shared/utils.js +20 -11
  121. package/out/shared/utils.js.map +1 -1
  122. package/package.json +4 -5
  123. package/out/language-server/inline-completion/codeDiffTracker.js.map +0 -1
  124. package/out/language-server/inline-completion/codePercentage.js.map +0 -1
  125. package/out/language-server/inline-completion/constants.js.map +0 -1
  126. package/out/language-server/inline-completion/diffUtils.js +0 -255
  127. package/out/language-server/inline-completion/diffUtils.js.map +0 -1
  128. package/out/language-server/inline-completion/editCompletionHandler.js.map +0 -1
  129. package/out/language-server/inline-completion/mergeRightUtils.d.ts +0 -25
  130. package/out/language-server/inline-completion/mergeRightUtils.js +0 -114
  131. package/out/language-server/inline-completion/mergeRightUtils.js.map +0 -1
  132. package/out/language-server/inline-completion/telemetry.js.map +0 -1
  133. package/out/language-server/inline-completion/trigger.js.map +0 -1
  134. /package/out/language-server/inline-completion/{constants.d.ts → contants/constants.d.ts} +0 -0
  135. /package/out/language-server/inline-completion/{constants.js → contants/constants.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.84](https://github.com/aws/language-servers/compare/lsp-codewhisperer/v0.0.83...lsp-codewhisperer/v0.0.84) (2025-10-09)
4
+
5
+
6
+ ### Features
7
+
8
+ * add model description to dropdown ([#2374](https://github.com/aws/language-servers/issues/2374)) ([ed8c6dd](https://github.com/aws/language-servers/commit/ed8c6dda1312f728e9ee7472f7ca447196ad9d84))
9
+ * **amazonq:** adding classification based retry strategy for chat ([#2234](https://github.com/aws/language-servers/issues/2234)) ([#2409](https://github.com/aws/language-servers/issues/2409)) ([15d1b1f](https://github.com/aws/language-servers/commit/15d1b1f5947a1b83dab65c9d3fef901ab8a033c9))
10
+ * **amazonq:** env var change for JupyterLab conversation history on refresh support ([#2395](https://github.com/aws/language-servers/issues/2395)) ([a908195](https://github.com/aws/language-servers/commit/a9081954bcaf20b7d0fbe0af11e61b8f82c7e82f))
11
+ * **amazonq:** support JupyterLab conversation history on refresh ([#2325](https://github.com/aws/language-servers/issues/2325)) ([0980351](https://github.com/aws/language-servers/commit/09803514d1ce31ca77a532161e071e1d037e3fb1))
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * add in-loop compaction ([#2387](https://github.com/aws/language-servers/issues/2387)) ([35f0795](https://github.com/aws/language-servers/commit/35f0795fa5d09f3610e6a29cb72d49f32cc5534e))
17
+ * addonly EDITS should be handled as COMPLETIONS ([#2133](https://github.com/aws/language-servers/issues/2133)) ([4f5a9da](https://github.com/aws/language-servers/commit/4f5a9dacf3bfd68aeb40920fb800adf001ed43d5))
18
+ * patch [#2133](https://github.com/aws/language-servers/issues/2133) and handle more variants of FIM suggestions ([#2407](https://github.com/aws/language-servers/issues/2407)) ([f3086d7](https://github.com/aws/language-servers/commit/f3086d71808bd49336e0df9ba30f5be5fda837c3))
19
+
20
+ ## [0.0.83](https://github.com/aws/language-servers/compare/lsp-codewhisperer/v0.0.82...lsp-codewhisperer/v0.0.83) (2025-10-01)
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * **amazonq:** escaping user input to mitigate xss issue ([#2360](https://github.com/aws/language-servers/issues/2360)) ([45b86be](https://github.com/aws/language-servers/commit/45b86bef1a93cf9ced6fbf0c222cf5410de04c81))
26
+ * **amazonq:** fix to add opt-out header to streaming client ([#2365](https://github.com/aws/language-servers/issues/2365)) ([692e77b](https://github.com/aws/language-servers/commit/692e77bc99770ac7d676928e95e3dc43bb91e7f0))
27
+ * **amazonq:** handle IAM credentials expiration field to be aws sdk versions compatible and add refresh logic to codewhisperer IAM client ([#2349](https://github.com/aws/language-servers/issues/2349)) ([5eb3768](https://github.com/aws/language-servers/commit/5eb3768bf020d61d0ade767d62e13839048146e4))
28
+ * **amazonq:** send full finding details to plugin, partial to agent ([#2356](https://github.com/aws/language-servers/issues/2356)) ([961e6ca](https://github.com/aws/language-servers/commit/961e6ca11b122481685f9f65b3da14c6a2497cc4))
29
+ * improve history management ([#2312](https://github.com/aws/language-servers/issues/2312)) ([#2357](https://github.com/aws/language-servers/issues/2357)) ([e7aa2a6](https://github.com/aws/language-servers/commit/e7aa2a6545bcb1a8238abfde69a05432be0b6615))
30
+ * optimize memory bank token usage and add new tab support ([#2366](https://github.com/aws/language-servers/issues/2366)) ([3057d56](https://github.com/aws/language-servers/commit/3057d56e4a3047d1715d6e3560e9f934d1de469c))
31
+ * private package mapping during artifact generation ([#2348](https://github.com/aws/language-servers/issues/2348)) ([d56bfa1](https://github.com/aws/language-servers/commit/d56bfa191954fac8068e2bf390c2d0b88ef8b168))
32
+ * trim new line when emitting error message ([#2359](https://github.com/aws/language-servers/issues/2359)) ([d8733a7](https://github.com/aws/language-servers/commit/d8733a75487f74815302b838802eccbf3ffec55e))
33
+
34
+
35
+ ### Reverts
36
+
37
+ * fix to add opt-out header to streaming client ([#2365](https://github.com/aws/language-servers/issues/2365)) ([#2370](https://github.com/aws/language-servers/issues/2370)) ([b29478f](https://github.com/aws/language-servers/commit/b29478fa1ecc58e331ff330ff79f46b0d8c38d9e))
38
+
39
+
40
+ ### Dependencies
41
+
42
+ * The following workspace dependencies were updated
43
+ * dependencies
44
+ * @aws/lsp-core bumped from ^0.0.15 to ^0.0.16
45
+
3
46
  ## [0.0.82](https://github.com/aws/language-servers/compare/lsp-codewhisperer/v0.0.81...lsp-codewhisperer/v0.0.82) (2025-09-24)
4
47
 
5
48
 
@@ -66,7 +66,6 @@ const activeUserTracker_1 = require("../../shared/activeUserTracker");
66
66
  const displayFindings_1 = require("./tools/qCodeAnalysis/displayFindings");
67
67
  const constants_3 = require("../../shared/constants");
68
68
  const IdleWorkspaceManager_1 = require("../workspaceContext/IdleWorkspaceManager");
69
- const escapeHTML = require("escape-html");
70
69
  const semanticSearch_1 = require("./tools/workspaceContext/semanticSearch");
71
70
  const memoryBankController_1 = require("./context/memorybank/memoryBankController");
72
71
  class AgenticChatController {
@@ -470,9 +469,10 @@ class AgenticChatController {
470
469
  });
471
470
  // Wait for the response to be completed before proceeding
472
471
  this.#log('Model Response: ', JSON.stringify(responseResult, null, 2));
473
- models = Object.values(responseResult.models).map(({ modelId, modelName }) => ({
472
+ models = Object.values(responseResult.models).map(({ modelId, modelName, description }) => ({
474
473
  id: modelId,
475
474
  name: modelName ?? modelId,
475
+ description: description ?? '',
476
476
  }));
477
477
  defaultModelId = responseResult.defaultModel?.modelId;
478
478
  // Cache the models with defaultModelId
@@ -506,7 +506,7 @@ class AgenticChatController {
506
506
  // Get models from cache or API
507
507
  const { models, defaultModelId, errorFromAPI } = await this.#fetchModelsWithCache();
508
508
  // Get the first fallback model option as default
509
- const defaultModelOption = modelSelection_1.FALLBACK_MODEL_OPTIONS[1];
509
+ const defaultModelOption = modelSelection_1.FALLBACK_MODEL_OPTIONS[0];
510
510
  const DEFAULT_MODEL_ID = defaultModelId || defaultModelOption?.id;
511
511
  const sessionResult = this.#chatSessionManagementService.getSession(params.tabId);
512
512
  const { data: session, success } = sessionResult;
@@ -565,11 +565,17 @@ class AgenticChatController {
565
565
  }
566
566
  async onChatPrompt(params, token) {
567
567
  // Phase 1: Initial Setup - This happens only once
568
- params.prompt.prompt = (0, utils_2.sanitizeInput)(params.prompt.prompt || '');
568
+ params.prompt.prompt = (0, utils_2.sanitizeInput)(params.prompt.prompt || '', true);
569
569
  IdleWorkspaceManager_1.IdleWorkspaceManager.recordActivityTimestamp();
570
+ const sessionResult = this.#chatSessionManagementService.getSession(params.tabId);
571
+ const { data: session, success } = sessionResult;
572
+ if (!success) {
573
+ return new server_interface_1.ResponseError(protocol_1.ErrorCodes.InternalError, sessionResult.error);
574
+ }
570
575
  // Memory Bank Creation Flow - Delegate to MemoryBankController
571
576
  if (this.#memoryBankController.isMemoryBankCreationRequest(params.prompt.prompt)) {
572
577
  this.#features.logging.info(`Memory Bank creation request detected for tabId: ${params.tabId}`);
578
+ session.isMemoryBankGeneration = true;
573
579
  // Store original prompt to prevent data loss on failure
574
580
  const originalPrompt = params.prompt.prompt;
575
581
  try {
@@ -639,19 +645,21 @@ class AgenticChatController {
639
645
  this.#features.logging.error(`Memory Bank preparation failed: ${error}`);
640
646
  // Restore original prompt to ensure no data loss
641
647
  params.prompt.prompt = originalPrompt;
648
+ // Reset memory bank flag since preparation failed
649
+ session.isMemoryBankGeneration = false;
642
650
  }
643
651
  }
644
652
  const maybeDefaultResponse = !params.prompt.command && (0, utils_1.getDefaultChatResponse)(params.prompt.prompt);
645
653
  if (maybeDefaultResponse) {
646
654
  return maybeDefaultResponse;
647
655
  }
648
- const sessionResult = this.#chatSessionManagementService.getSession(params.tabId);
649
- const { data: session, success } = sessionResult;
650
- if (!success) {
651
- return new server_interface_1.ResponseError(protocol_1.ErrorCodes.InternalError, sessionResult.error);
652
- }
653
656
  const compactIds = session.getAllDeferredCompactMessageIds();
654
657
  await this.#invalidateCompactCommand(params.tabId, compactIds);
658
+ // Set compactionDeclined flag if there were pending compaction requests
659
+ // This prevents endless compaction warning loops when user declines compaction once
660
+ if (compactIds.length > 0) {
661
+ session.compactionDeclined = true;
662
+ }
655
663
  session.rejectAllDeferredToolExecutions(new toolShared_1.ToolApprovalException('Command ignored: new prompt', false));
656
664
  await this.#invalidateAllShellCommands(params.tabId, session);
657
665
  const metric = new metric_1.Metric({
@@ -683,6 +691,10 @@ class AgenticChatController {
683
691
  session.abortRequest();
684
692
  const compactIds = session.getAllDeferredCompactMessageIds();
685
693
  await this.#invalidateCompactCommand(params.tabId, compactIds);
694
+ // Set compactionDeclined flag if there were pending compaction requests
695
+ if (compactIds.length > 0) {
696
+ session.compactionDeclined = true;
697
+ }
686
698
  void this.#invalidateAllShellCommands(params.tabId, session);
687
699
  session.rejectAllDeferredToolExecutions(new lsp_core_1.CancellationError('user'));
688
700
  // Then update UI to inform the user
@@ -696,6 +708,13 @@ class AgenticChatController {
696
708
  await this.#telemetryController.emitAddMessageMetric(params.tabId, metric.metric, 'Cancelled');
697
709
  });
698
710
  session.setConversationType('AgenticChat');
711
+ // Set up delay notification callback to show retry progress to users
712
+ session.setDelayNotificationCallback(notification => {
713
+ if (notification.thresholdExceeded) {
714
+ this.#log(`Updating progress message: ${notification.message}`);
715
+ void chatResultStream.updateProgressMessage(notification.message);
716
+ }
717
+ });
699
718
  const additionalContext = await this.#additionalContextProvider.getAdditionalContext(triggerContext, params.tabId, params.context, params.prompt.prompt);
700
719
  // Add active file to context list if it's not already there
701
720
  const activeFile = triggerContext.text &&
@@ -738,7 +757,12 @@ class AgenticChatController {
738
757
  finalResult = await this.#runAgentLoop(initialRequestInput, session, metric, chatResultStream, params.tabId, promptId, session.conversationId, token, triggerContext.documentReference, additionalContext);
739
758
  }
740
759
  // Result Handling - This happens only once
741
- return await this.#handleFinalResult(finalResult, session, params.tabId, metric, triggerContext, isNewConversation, chatResultStream);
760
+ const result = await this.#handleFinalResult(finalResult, session, params.tabId, metric, triggerContext, isNewConversation, chatResultStream);
761
+ // Reset compactionDeclined flag after successful completion
762
+ if (session.compactionDeclined) {
763
+ session.compactionDeclined = false;
764
+ }
765
+ return result;
742
766
  }
743
767
  catch (err) {
744
768
  // HACK: the chat-client needs to have a partial event with the associated messageId sent before it can accept the final result.
@@ -780,20 +804,20 @@ class AgenticChatController {
780
804
  /**
781
805
  * Prepares the initial request input for the chat prompt
782
806
  */
783
- #getCompactionRequestInput(session) {
807
+ #getCompactionRequestInput(session, toolResults) {
784
808
  this.#debug('Preparing compaction request input');
785
809
  // Get profileArn from the service manager if available
786
810
  const profileArn = this.#serviceManager?.getActiveProfileArn();
787
- const requestInput = this.#triggerContext.getCompactionChatCommandInput(profileArn, this.#getTools(session), session.modelId, this.#origin);
811
+ const requestInput = this.#triggerContext.getCompactionChatCommandInput(profileArn, this.#getTools(session), session.modelId, this.#origin, toolResults);
788
812
  return requestInput;
789
813
  }
790
814
  /**
791
815
  * Runs the compaction, making requests and processing tool uses until completion
792
816
  */
793
- #shouldCompact(currentRequestCount) {
794
- // 80% of 570K limit
795
- if (currentRequestCount > 456_000) {
796
- this.#debug(`Current request total character count is: ${currentRequestCount}, prompting user to compact`);
817
+ #shouldCompact(currentRequestCount, session) {
818
+ const EFFECTIVE_COMPACTION_THRESHOLD = constants_2.COMPACTION_CHARACTER_THRESHOLD - constants_2.COMPACTION_PROMPT.length;
819
+ if (currentRequestCount > EFFECTIVE_COMPACTION_THRESHOLD && !session.compactionDeclined) {
820
+ this.#debug(`Current request total character count is: ${currentRequestCount}, prompting user to compact (threshold: ${EFFECTIVE_COMPACTION_THRESHOLD})`);
797
821
  return true;
798
822
  }
799
823
  else {
@@ -821,7 +845,7 @@ class AgenticChatController {
821
845
  if (currentMessage) {
822
846
  // Get and process the messages from history DB to maintain invariants for service requests
823
847
  try {
824
- const { history: historyMessages, historyCount: historyCharCount } = this.#chatHistoryDb.fixAndGetHistory(tabId, conversationIdentifier ?? '', currentMessage, []);
848
+ const { history: historyMessages, historyCount: historyCharCount } = this.#chatHistoryDb.fixAndGetHistory(tabId, currentMessage, []);
825
849
  messages = historyMessages;
826
850
  characterCount = historyCharCount;
827
851
  }
@@ -913,6 +937,8 @@ class AgenticChatController {
913
937
  let shouldDisplayMessage = true;
914
938
  let currentRequestCount = 0;
915
939
  const pinnedContext = additionalContext?.filter(item => item.pinned);
940
+ // Store initial non-empty prompt for compaction handoff
941
+ const initialPrompt = initialRequestInput.conversationState?.currentMessage?.userInputMessage?.content?.trim() || '';
916
942
  metric.recordStart();
917
943
  this.logSystemInformation();
918
944
  while (true) {
@@ -939,7 +965,7 @@ class AgenticChatController {
939
965
  if (currentMessage) {
940
966
  // Get and process the messages from history DB to maintain invariants for service requests
941
967
  try {
942
- const { history: historyMessages, historyCount: historyCharacterCount, currentCount: currentInputCount, } = this.#chatHistoryDb.fixAndGetHistory(tabId, conversationId, currentMessage, pinnedContextMessages);
968
+ const { history: historyMessages, historyCount: historyCharacterCount, currentCount: currentInputCount, } = this.#chatHistoryDb.fixAndGetHistory(tabId, currentMessage, pinnedContextMessages);
943
969
  messages = historyMessages;
944
970
  currentRequestCount = currentInputCount + historyCharacterCount;
945
971
  this.#debug(`Request total character count: ${currentRequestCount}`);
@@ -962,6 +988,34 @@ class AgenticChatController {
962
988
  this.#llmRequestStartTime = Date.now();
963
989
  // Phase 3: Request Execution
964
990
  currentRequestInput = (0, utils_2.sanitizeRequestInput)(currentRequestInput);
991
+ if (this.#shouldCompact(currentRequestCount, session)) {
992
+ this.#features.logging.info(`Entering mid-loop compaction at iteration ${iterationCount} with ${currentRequestCount} characters`);
993
+ this.#telemetryController.emitMidLoopCompaction(currentRequestCount, iterationCount, this.#features.runtime.serverInfo.version ?? '');
994
+ const messageId = this.#getMessageIdForCompact((0, uuid_1.v4)());
995
+ const confirmationResult = this.#processCompactConfirmation(messageId, currentRequestCount);
996
+ const cachedButtonBlockId = await chatResultStream.writeResultBlock(confirmationResult);
997
+ await this.waitForCompactApproval(messageId, chatResultStream, cachedButtonBlockId, session);
998
+ // Run compaction
999
+ const toolResults = currentRequestInput.conversationState?.currentMessage?.userInputMessage?.userInputMessageContext
1000
+ ?.toolResults || [];
1001
+ const compactionRequestInput = this.#getCompactionRequestInput(session, toolResults);
1002
+ const compactionResult = await this.#runCompaction(compactionRequestInput, session, metric, chatResultStream, tabId, promptId, types_1.CompactHistoryActionType.Nudge, session.conversationId, token, documentReference);
1003
+ if (!compactionResult.success) {
1004
+ this.#features.logging.error(`Compaction failed: ${compactionResult.error}`);
1005
+ return compactionResult;
1006
+ }
1007
+ // Show compaction summary to user before continuing
1008
+ await chatResultStream.writeResultBlock({
1009
+ type: 'answer',
1010
+ body: (compactionResult.data?.chatResult.body || '') +
1011
+ '\n\nConversation history has been compacted successfully!',
1012
+ messageId: (0, uuid_1.v4)(),
1013
+ });
1014
+ currentRequestInput = this.#updateRequestInputWithToolResults(currentRequestInput, [], constants_2.MID_LOOP_COMPACTION_HANDOFF_PROMPT + initialPrompt);
1015
+ shouldDisplayMessage = false;
1016
+ this.#features.logging.info(`Completed mid-loop compaction, restarting loop with handoff prompt`);
1017
+ continue;
1018
+ }
965
1019
  // Note: these logs are very noisy, but contain information redacted on the backend.
966
1020
  this.#debug(`generateAssistantResponse/SendMessage Request: ${JSON.stringify(currentRequestInput, this.#imageReplacer, 2)}`);
967
1021
  const response = await session.getChatResponse(currentRequestInput);
@@ -980,7 +1034,7 @@ class AgenticChatController {
980
1034
  }
981
1035
  else {
982
1036
  this.#chatHistoryDb.addMessage(tabId, 'cwc', conversationIdentifier, {
983
- body: escapeHTML(currentMessage.userInputMessage?.content ?? ''),
1037
+ body: currentMessage.userInputMessage?.content ?? '',
984
1038
  type: 'prompt',
985
1039
  userIntent: currentMessage.userInputMessage?.userIntent,
986
1040
  origin: currentMessage.userInputMessage?.origin,
@@ -1104,7 +1158,7 @@ class AgenticChatController {
1104
1158
  }
1105
1159
  currentRequestInput = this.#updateRequestInputWithToolResults(currentRequestInput, toolResults, content);
1106
1160
  }
1107
- if (this.#shouldCompact(currentRequestCount)) {
1161
+ if (this.#shouldCompact(currentRequestCount, session)) {
1108
1162
  this.#telemetryController.emitCompactNudge(currentRequestCount, this.#features.runtime.serverInfo.version ?? '');
1109
1163
  const messageId = this.#getMessageIdForCompact((0, uuid_1.v4)());
1110
1164
  const confirmationResult = this.#processCompactConfirmation(messageId, currentRequestCount);
@@ -1322,7 +1376,9 @@ class AgenticChatController {
1322
1376
  [toolConstants_1.FILE_SEARCH]: { Tool: fileSearch_1.FileSearch },
1323
1377
  };
1324
1378
  const { Tool } = toolMap[toolUse.name];
1325
- const tool = new Tool(this.#features);
1379
+ const tool = toolUse.name === toolConstants_1.FS_READ && session.isMemoryBankGeneration
1380
+ ? new Tool(this.#features, constants_2.FSREAD_MEMORY_BANK_MAX_PER_FILE, constants_2.FSREAD_MEMORY_BANK_MAX_TOTAL)
1381
+ : new Tool(this.#features);
1326
1382
  // For MCP tools, get the permission from McpManager
1327
1383
  // const permission = McpManager.instance.getToolPerm('Built-in', toolUse.name)
1328
1384
  // If permission is 'alwaysAllow', we don't need to ask for acceptance
@@ -1428,6 +1484,25 @@ class AgenticChatController {
1428
1484
  const ws = this.#getWritableStream(chatResultStream, toolUse);
1429
1485
  const result = await this.#features.agent.runTool(toolUse.name, toolUse.input, token, ws);
1430
1486
  let toolResultContent;
1487
+ if (toolUse.name === codeReview_1.CodeReview.toolName) {
1488
+ // no need to write tool result for code review, this is handled by model via chat
1489
+ // Push result in message so that it is picked by IDE plugin to show in issues panel
1490
+ const codeReviewResult = result;
1491
+ if (codeReviewResult?.output?.kind === 'json' &&
1492
+ codeReviewResult.output.success &&
1493
+ codeReviewResult.output.content?.findingsByFile) {
1494
+ await chatResultStream.writeResultBlock({
1495
+ type: 'tool',
1496
+ messageId: toolUse.toolUseId + codeReviewConstants_1.CODE_REVIEW_FINDINGS_MESSAGE_SUFFIX,
1497
+ body: codeReviewResult.output.content.findingsByFile,
1498
+ });
1499
+ codeReviewResult.output.content = {
1500
+ codeReviewId: codeReviewResult.output.content.codeReviewId,
1501
+ message: codeReviewResult.output.content.message,
1502
+ findingsByFileSimplified: codeReviewResult.output.content.findingsByFileSimplified,
1503
+ };
1504
+ }
1505
+ }
1431
1506
  if (typeof result === 'string') {
1432
1507
  toolResultContent = { text: result };
1433
1508
  }
@@ -1499,18 +1574,6 @@ class AgenticChatController {
1499
1574
  await chatResultStream.writeResultBlock(chatResult);
1500
1575
  break;
1501
1576
  case codeReview_1.CodeReview.toolName:
1502
- // no need to write tool result for code review, this is handled by model via chat
1503
- // Push result in message so that it is picked by IDE plugin to show in issues panel
1504
- const codeReviewResult = result;
1505
- if (codeReviewResult?.output?.kind === 'json' &&
1506
- codeReviewResult.output.success &&
1507
- codeReviewResult.output.content?.findingsByFile) {
1508
- await chatResultStream.writeResultBlock({
1509
- type: 'tool',
1510
- messageId: toolUse.toolUseId + codeReviewConstants_1.CODE_REVIEW_FINDINGS_MESSAGE_SUFFIX,
1511
- body: codeReviewResult.output.content.findingsByFile,
1512
- });
1513
- }
1514
1577
  break;
1515
1578
  case displayFindings_1.DisplayFindings.toolName:
1516
1579
  // no need to write tool result for code review, this is handled by model via chat
@@ -2017,7 +2080,7 @@ class AgenticChatController {
2017
2080
  body: constants_2.COMPACTION_HEADER_BODY,
2018
2081
  buttons,
2019
2082
  };
2020
- const body = (0, constants_2.COMPACTION_BODY)(Math.round((characterCount / chatDb_1.MaxOverallCharacters) * 100));
2083
+ const body = (0, constants_2.COMPACTION_BODY)(Math.round((characterCount / constants_2.MAX_OVERALL_CHARACTERS) * 100));
2021
2084
  return {
2022
2085
  type: 'tool',
2023
2086
  messageId,
@@ -2568,13 +2631,15 @@ class AgenticChatController {
2568
2631
  .filter(prompt => prompt.length > 0)),
2569
2632
  },
2570
2633
  });
2634
+ // Reset memory bank flag after completion
2635
+ session.isMemoryBankGeneration = false;
2571
2636
  return chatResultStream.getResult();
2572
2637
  }
2573
2638
  /**
2574
2639
  * Handles errors that occur during the request
2575
2640
  */
2576
2641
  async #handleRequestError(conversationId, err, errorMessageId, tabId, metric, agenticCodingMode) {
2577
- const errorMessage = (0, utils_2.getErrorMsg)(err) ?? constants_2.GENERIC_ERROR_MS;
2642
+ const errorMessage = ((0, utils_2.getErrorMsg)(err) ?? constants_2.GENERIC_ERROR_MS).replace(/[\r\n]+/g, ' '); // replace new lines with empty space
2578
2643
  const requestID = (0, utils_2.getRequestID)(err) ?? '';
2579
2644
  metric.setDimension('cwsprChatResponseCode', (0, utils_2.getHttpStatusCode)(err) ?? 0);
2580
2645
  metric.setDimension('languageServerVersion', this.#features.runtime.serverInfo.version);
@@ -2585,6 +2650,11 @@ class AgenticChatController {
2585
2650
  metric.metric.cwsprChatConversationId = conversationId;
2586
2651
  const errorCode = err.code ?? '';
2587
2652
  await this.#telemetryController.emitAddMessageMetric(tabId, metric.metric, 'Failed', errorMessage, errorCode);
2653
+ // Reset memory bank flag on request error
2654
+ const sessionResult = this.#chatSessionManagementService.getSession(tabId);
2655
+ if (sessionResult.success) {
2656
+ sessionResult.data.isMemoryBankGeneration = false;
2657
+ }
2588
2658
  if ((0, utils_2.isUsageLimitError)(err)) {
2589
2659
  if (this.#paidTierMode !== 'paidtier') {
2590
2660
  this.setPaidTierMode(tabId, 'freetier-limit');