@aws/lsp-codewhisperer 0.0.64 → 0.0.65

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 (70) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/out/client/token/bearer-token-service.json +1 -1
  3. package/out/language-server/agenticChat/agenticChatController.d.ts +6 -0
  4. package/out/language-server/agenticChat/agenticChatController.js +132 -11
  5. package/out/language-server/agenticChat/agenticChatController.js.map +1 -1
  6. package/out/language-server/agenticChat/context/additionalContextProvider.d.ts +1 -1
  7. package/out/language-server/agenticChat/context/additionalContextProvider.js +8 -3
  8. package/out/language-server/agenticChat/context/additionalContextProvider.js.map +1 -1
  9. package/out/language-server/agenticChat/qAgenticChatServer.js +5 -1
  10. package/out/language-server/agenticChat/qAgenticChatServer.js.map +1 -1
  11. package/out/language-server/agenticChat/tools/executeBash.d.ts +16 -0
  12. package/out/language-server/agenticChat/tools/executeBash.js +92 -1
  13. package/out/language-server/agenticChat/tools/executeBash.js.map +1 -1
  14. package/out/language-server/agenticChat/tools/mcp/mcpManager.js +1 -1
  15. package/out/language-server/agenticChat/tools/mcp/mcpManager.js.map +1 -1
  16. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReview.d.ts +211 -0
  17. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReview.js +630 -0
  18. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReview.js.map +1 -0
  19. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewConstants.d.ts +34 -0
  20. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewConstants.js +200 -0
  21. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewConstants.js.map +1 -0
  22. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewErrors.d.ts +12 -0
  23. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewErrors.js +32 -0
  24. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewErrors.js.map +1 -0
  25. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewSchemas.d.ts +289 -0
  26. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewSchemas.js +140 -0
  27. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewSchemas.js.map +1 -0
  28. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewTypes.d.ts +58 -0
  29. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewTypes.js +3 -0
  30. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewTypes.js.map +1 -0
  31. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewUtils.d.ts +156 -0
  32. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewUtils.js +363 -0
  33. package/out/language-server/agenticChat/tools/qCodeAnalysis/qCodeReviewUtils.js.map +1 -0
  34. package/out/language-server/agenticChat/tools/toolServer.d.ts +1 -0
  35. package/out/language-server/agenticChat/tools/toolServer.js +90 -39
  36. package/out/language-server/agenticChat/tools/toolServer.js.map +1 -1
  37. package/out/language-server/chat/telemetry/chatTelemetryController.d.ts +3 -3
  38. package/out/language-server/chat/telemetry/chatTelemetryController.js +13 -3
  39. package/out/language-server/chat/telemetry/chatTelemetryController.js.map +1 -1
  40. package/out/language-server/configuration/qConfigurationServer.d.ts +1 -0
  41. package/out/language-server/configuration/qConfigurationServer.js.map +1 -1
  42. package/out/language-server/inline-completion/codeWhispererServer.js +58 -41
  43. package/out/language-server/inline-completion/codeWhispererServer.js.map +1 -1
  44. package/out/language-server/workspaceContext/artifactManager.d.ts +4 -1
  45. package/out/language-server/workspaceContext/artifactManager.js +16 -1
  46. package/out/language-server/workspaceContext/artifactManager.js.map +1 -1
  47. package/out/language-server/workspaceContext/dependency/dependencyDiscoverer.d.ts +2 -1
  48. package/out/language-server/workspaceContext/dependency/dependencyDiscoverer.js +9 -6
  49. package/out/language-server/workspaceContext/dependency/dependencyDiscoverer.js.map +1 -1
  50. package/out/language-server/workspaceContext/dependency/dependencyHandler/LanguageDependencyHandler.d.ts +7 -2
  51. package/out/language-server/workspaceContext/dependency/dependencyHandler/LanguageDependencyHandler.js +20 -7
  52. package/out/language-server/workspaceContext/dependency/dependencyHandler/LanguageDependencyHandler.js.map +1 -1
  53. package/out/language-server/workspaceContext/dependency/dependencyHandler/LanguageDependencyHandlerFactory.d.ts +2 -2
  54. package/out/language-server/workspaceContext/dependency/dependencyHandler/LanguageDependencyHandlerFactory.js +4 -4
  55. package/out/language-server/workspaceContext/dependency/dependencyHandler/LanguageDependencyHandlerFactory.js.map +1 -1
  56. package/out/language-server/workspaceContext/fileUploadJobManager.js +3 -1
  57. package/out/language-server/workspaceContext/fileUploadJobManager.js.map +1 -1
  58. package/out/language-server/workspaceContext/workspaceContextServer.js +32 -19
  59. package/out/language-server/workspaceContext/workspaceContextServer.js.map +1 -1
  60. package/out/language-server/workspaceContext/workspaceFolderManager.d.ts +5 -3
  61. package/out/language-server/workspaceContext/workspaceFolderManager.js +80 -59
  62. package/out/language-server/workspaceContext/workspaceFolderManager.js.map +1 -1
  63. package/out/shared/amazonQServiceManager/configurationUtils.js +6 -0
  64. package/out/shared/amazonQServiceManager/configurationUtils.js.map +1 -1
  65. package/out/shared/telemetry/telemetryService.d.ts +2 -0
  66. package/out/shared/telemetry/telemetryService.js +4 -1
  67. package/out/shared/telemetry/telemetryService.js.map +1 -1
  68. package/out/shared/telemetry/types.d.ts +2 -0
  69. package/out/shared/telemetry/types.js.map +1 -1
  70. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.65](https://github.com/aws/language-servers/compare/lsp-codewhisperer/v0.0.64...lsp-codewhisperer/v0.0.65) (2025-07-15)
4
+
5
+
6
+ ### Features
7
+
8
+ * **amazonq:** add a/b testing info into agenticChat toolkit metrics ([#1898](https://github.com/aws/language-servers/issues/1898)) ([6ab9b2c](https://github.com/aws/language-servers/commit/6ab9b2cef0125846c2f20fd8554f591808b59cd0))
9
+ * **amazonq:** added full system information to the logs ([#1875](https://github.com/aws/language-servers/issues/1875)) ([7795c6b](https://github.com/aws/language-servers/commit/7795c6b43274211731aa9bb295b41ec89db41a6d))
10
+ * **amazonq:** Adding QCodeReview tool to amazonQ ([#1882](https://github.com/aws/language-servers/issues/1882)) ([07e343b](https://github.com/aws/language-servers/commit/07e343b9fcef319bdbec80c48388e44b4b19269a))
11
+ * **amazonq:** allow opt-out for workspace context server ([#1867](https://github.com/aws/language-servers/issues/1867)) ([72b6d76](https://github.com/aws/language-servers/commit/72b6d76c5ed8e240aad6be80f65eab3497caaacf))
12
+ * **chat-client:** add built-in tool permission and enable auto-approve ([#1890](https://github.com/aws/language-servers/issues/1890)) ([03b59c8](https://github.com/aws/language-servers/commit/03b59c8fba58db0f6b6c387cf5d53227c3f54673))
13
+ * **chat-client:** handle keyboard shortcut for run/reject/stop shell commands and tooltips ([#1885](https://github.com/aws/language-servers/issues/1885)) ([f8e9461](https://github.com/aws/language-servers/commit/f8e94615b5ce8a3f4bf8837627fa4816a09cbef2))
14
+ * update UserTriggerDecisionEventStreakLengthInteger min value ([#1878](https://github.com/aws/language-servers/issues/1878)) ([e06f180](https://github.com/aws/language-servers/commit/e06f18017864ea33e316059a708cb87aa6d8c562))
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **amazonq:** additional checks for binary and credential files ([#1866](https://github.com/aws/language-servers/issues/1866)) ([76656c9](https://github.com/aws/language-servers/commit/76656c9b2bb5080f64f581bb3b39cd55a3015bdf))
20
+ * **amazonq:** catch mcp initialization errors ([#1873](https://github.com/aws/language-servers/issues/1873)) ([afdd6a4](https://github.com/aws/language-servers/commit/afdd6a4bd1db7c3990a7a279ebbbfbe0640e27c3))
21
+ * **chat-client:** revert for add built-in tool permission and enable auto-approve ([#1890](https://github.com/aws/language-servers/issues/1890)) ([#1900](https://github.com/aws/language-servers/issues/1900)) ([34b41b8](https://github.com/aws/language-servers/commit/34b41b8f87c21d2ee6b98643339dbdfa71efcb77))
22
+ * **chat-client:** revert for amazon q keyboard shortcuts feature ([#1901](https://github.com/aws/language-servers/issues/1901)) ([522f8de](https://github.com/aws/language-servers/commit/522f8de6dba8dfa9b4363934cd7fcea905add1ce))
23
+ * Disable Concurrent inline completion handler ([#1880](https://github.com/aws/language-servers/issues/1880)) ([61eeb8c](https://github.com/aws/language-servers/commit/61eeb8c93b5454c5a99ebb79b5593007d08007e5))
24
+ * Forward slash shown in rules list in multi-root workspaces on windows ([#1855](https://github.com/aws/language-servers/issues/1855)) ([061caa6](https://github.com/aws/language-servers/commit/061caa6450946e20cd1630b92f9b6dada8058edd))
25
+
26
+
27
+ ### Reverts
28
+
29
+ * adding streakLength back for UserTriggerDecisionEvent ([#1877](https://github.com/aws/language-servers/issues/1877)) ([b199100](https://github.com/aws/language-servers/commit/b199100153aa0629890c49e12a56efbb9c627154))
30
+
3
31
  ## [0.0.64](https://github.com/aws/language-servers/compare/lsp-codewhisperer/v0.0.63...lsp-codewhisperer/v0.0.64) (2025-07-11)
4
32
 
5
33
 
@@ -6453,7 +6453,7 @@
6453
6453
  },
6454
6454
  "UserTriggerDecisionEventStreakLengthInteger": {
6455
6455
  "type": "integer",
6456
- "min": 0
6456
+ "min": -1
6457
6457
  },
6458
6458
  "ValidationException": {
6459
6459
  "type": "structure",
@@ -16,9 +16,14 @@ import { ChatSessionService } from '../chat/chatSessionService';
16
16
  import { AgenticChatResultStream } from './agenticChatResultStream';
17
17
  import { AdditionalContentEntryAddition } from './context/agenticChatTriggerContext';
18
18
  import { PaidTierMode } from '../paidTier/paidTier';
19
+ import { UserContext } from '../../client/token/codewhispererbearertokenclient';
19
20
  type ChatHandlers = Omit<LspHandlers<Chat>, 'openTab' | 'sendChatUpdate' | 'sendContextCommands' | 'onListConversations' | 'onConversationClick' | 'onListMcpServers' | 'onMcpServerClick' | 'onTabBarAction' | 'getSerializedChat' | 'chatOptionsUpdate' | 'onListRules' | 'sendPinnedContext' | 'onActiveEditorChanged' | 'onPinnedContextAdd' | 'onPinnedContextRemove' | 'onOpenFileDialog' | 'onListAvailableModels'>;
20
21
  export declare class AgenticChatController implements ChatHandlers {
21
22
  #private;
23
+ /**
24
+ * Logs system information that can be helpful for debugging customer issues
25
+ */
26
+ private logSystemInformation;
22
27
  constructor(chatSessionManagementService: ChatSessionManagementService, features: Features, telemetryService: TelemetryService, serviceManager?: AmazonQBaseServiceManager);
23
28
  onExecuteCommand(params: ExecuteCommandParams, _token: CancellationToken): Promise<any>;
24
29
  onButtonClick(params: ButtonClickParams): Promise<ButtonClickResult>;
@@ -143,5 +148,6 @@ export declare class AgenticChatController implements ChatHandlers {
143
148
  onPromptInputOptionChange(params: PromptInputOptionChangeParams): void;
144
149
  updateConfiguration: (newConfig: AmazonQWorkspaceConfig) => void;
145
150
  restorePreviousChats(): Promise<void>;
151
+ scheduleABTestingFetching(userContext: UserContext | undefined): void;
146
152
  }
147
153
  export {};
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.AgenticChatController = void 0;
8
8
  const crypto = require("crypto");
9
9
  const path = require("path");
10
+ const os = require("os");
10
11
  const codewhisperer_streaming_1 = require("@amzn/codewhisperer-streaming");
11
12
  const protocol_1 = require("@aws/language-server-runtimes/protocol");
12
13
  const protocol_2 = require("@aws/language-server-runtimes/protocol");
@@ -49,6 +50,8 @@ const errors_2 = require("./errors");
49
50
  const vscode_uri_1 = require("vscode-uri");
50
51
  const executeBash_2 = require("./tools/executeBash");
51
52
  const userWrittenCodeTracker_1 = require("../../shared/userWrittenCodeTracker");
53
+ const qCodeReview_1 = require("./tools/qCodeAnalysis/qCodeReview");
54
+ const qCodeReviewConstants_1 = require("./tools/qCodeAnalysis/qCodeReviewConstants");
52
55
  const mcpEventHandler_1 = require("./tools/mcp/mcpEventHandler");
53
56
  const mcpUtils_1 = require("./tools/mcp/mcpUtils");
54
57
  const mcpManager_1 = require("./tools/mcp/mcpManager");
@@ -85,6 +88,9 @@ class AgenticChatController {
85
88
  #timeToFirstChunk = -1;
86
89
  #timeBetweenChunks = [];
87
90
  #lastChunkTime = 0;
91
+ // A/B testing allocation
92
+ #abTestingFetchingTimeout;
93
+ #abTestingAllocation;
88
94
  /**
89
95
  * Determines the appropriate message ID for a tool use based on tool type and name
90
96
  * @param toolType The type of tool being used
@@ -96,6 +102,23 @@ class AgenticChatController {
96
102
  // Return plain toolUseId for executeBash, add "_permission" suffix for all other tools
97
103
  return toolUse.name === 'executeBash' || toolType === 'executeBash' ? toolUseId : `${toolUseId}_permission`;
98
104
  }
105
+ /**
106
+ * Logs system information that can be helpful for debugging customer issues
107
+ */
108
+ logSystemInformation() {
109
+ const clientInfo = this.#features.lsp.getClientInitializeParams()?.clientInfo;
110
+ const systemInfo = {
111
+ languageServerVersion: this.#features.runtime.serverInfo.version ?? 'unknown',
112
+ clientName: clientInfo?.name ?? 'unknown',
113
+ clientVersion: clientInfo?.version ?? 'unknown',
114
+ OS: os.platform(),
115
+ OSVersion: os.release(),
116
+ ComputeEnv: process.env.COMPUTE_ENV ?? 'unknown',
117
+ extensionVersion: this.#features.lsp.getClientInitializeParams()?.initializationOptions?.aws?.clientInfo?.extension
118
+ ?.version,
119
+ };
120
+ this.#features.logging.info(`System Information: ${JSON.stringify(systemInfo)}`);
121
+ }
99
122
  constructor(chatSessionManagementService, features, telemetryService, serviceManager) {
100
123
  this.#features = features;
101
124
  this.#chatSessionManagementService = chatSessionManagementService;
@@ -162,7 +185,7 @@ class AgenticChatController {
162
185
  try {
163
186
  await this.#undoFileChange(toolUseId, session.data);
164
187
  this.#updateUndoButtonAfterClick(params.tabId, toolUseId, session.data);
165
- this.#telemetryController.emitInteractWithAgenticChat('RejectDiff', params.tabId, session.data?.pairProgrammingMode, session.data?.getConversationType());
188
+ this.#telemetryController.emitInteractWithAgenticChat('RejectDiff', params.tabId, session.data?.pairProgrammingMode, session.data?.getConversationType(), this.#abTestingAllocation?.experimentName, this.#abTestingAllocation?.userVariation);
166
189
  }
167
190
  catch (err) {
168
191
  return { success: false, failureReason: err.message };
@@ -371,6 +394,7 @@ class AgenticChatController {
371
394
  this.#contextCommandsProvider?.dispose();
372
395
  this.#userWrittenCodeTracker?.dispose();
373
396
  this.#mcpEventHandler.dispose();
397
+ clearInterval(this.#abTestingFetchingTimeout);
374
398
  }
375
399
  async onListConversations(params) {
376
400
  return this.#tabBarController.onListConversations(params);
@@ -437,6 +461,8 @@ class AgenticChatController {
437
461
  await this.#invalidateAllShellCommands(params.tabId, session);
438
462
  const metric = new metric_1.Metric({
439
463
  cwsprChatConversationType: 'AgenticChat',
464
+ experimentName: this.#abTestingAllocation?.experimentName,
465
+ userVariation: this.#abTestingAllocation?.userVariation,
440
466
  });
441
467
  try {
442
468
  const triggerContext = await this.#getTriggerContext(params, metric);
@@ -462,7 +488,7 @@ class AgenticChatController {
462
488
  await this.#showUndoAllIfRequired(chatResultStream, session);
463
489
  await chatResultStream.updateOngoingProgressResult('Canceled');
464
490
  // Finally, send telemetry/metrics
465
- this.#telemetryController.emitInteractWithAgenticChat('StopChat', params.tabId, session.pairProgrammingMode, session.getConversationType());
491
+ this.#telemetryController.emitInteractWithAgenticChat('StopChat', params.tabId, session.pairProgrammingMode, session.getConversationType(), this.#abTestingAllocation?.experimentName, this.#abTestingAllocation?.userVariation);
466
492
  metric.setDimension('languageServerVersion', this.#features.runtime.serverInfo.version);
467
493
  metric.setDimension('codewhispererCustomizationArn', this.#customizationArn);
468
494
  metric.setDimension('enabled', session.pairProgrammingMode);
@@ -470,8 +496,11 @@ class AgenticChatController {
470
496
  });
471
497
  session.setConversationType('AgenticChat');
472
498
  const additionalContext = await this.#additionalContextProvider.getAdditionalContext(triggerContext, params.tabId, params.context);
473
- // Add active file to context list if it exists
474
- const activeFile = triggerContext.text && triggerContext.relativeFilePath && triggerContext.activeFilePath
499
+ // Add active file to context list if it's not already there
500
+ const activeFile = triggerContext.text &&
501
+ triggerContext.relativeFilePath &&
502
+ triggerContext.activeFilePath &&
503
+ !additionalContext.some(item => item.path === triggerContext.activeFilePath)
475
504
  ? [
476
505
  {
477
506
  name: path.basename(triggerContext.relativeFilePath),
@@ -546,6 +575,7 @@ class AgenticChatController {
546
575
  let iterationCount = 0;
547
576
  let shouldDisplayMessage = true;
548
577
  metric.recordStart();
578
+ this.logSystemInformation();
549
579
  while (true) {
550
580
  iterationCount++;
551
581
  this.#debug(`Agent loop iteration ${iterationCount} for conversation id:`, conversationIdentifier || '');
@@ -683,7 +713,7 @@ class AgenticChatController {
683
713
  if (pendingToolUses.length === 0) {
684
714
  this.recordChunk('agent_loop_done');
685
715
  // No more tool uses, we're done
686
- this.#telemetryController.emitAgencticLoop_InvokeLLM(response.$metadata.requestId, conversationId, 'AgenticChat', undefined, undefined, 'Succeeded', this.#features.runtime.serverInfo.version ?? '', session.modelId, llmLatency, this.#toolCallLatencies, this.#timeToFirstChunk, this.#timeBetweenChunks, session.pairProgrammingMode);
716
+ this.#telemetryController.emitAgencticLoop_InvokeLLM(response.$metadata.requestId, conversationId, 'AgenticChat', undefined, undefined, 'Succeeded', this.#features.runtime.serverInfo.version ?? '', session.modelId, llmLatency, this.#toolCallLatencies, this.#timeToFirstChunk, this.#timeBetweenChunks, session.pairProgrammingMode, this.#abTestingAllocation?.experimentName, this.#abTestingAllocation?.userVariation);
687
717
  finalResult = result;
688
718
  break;
689
719
  }
@@ -704,7 +734,7 @@ class AgenticChatController {
704
734
  metric.setDimension('requestIds', metric.metric.requestIds);
705
735
  const toolNames = this.#toolUseLatencies.map(item => item.toolName);
706
736
  const toolUseIds = this.#toolUseLatencies.map(item => item.toolUseId);
707
- this.#telemetryController.emitAgencticLoop_InvokeLLM(response.$metadata.requestId, conversationId, 'AgenticChatWithToolUse', toolNames ?? undefined, toolUseIds ?? undefined, 'Succeeded', this.#features.runtime.serverInfo.version ?? '', session.modelId, llmLatency, this.#toolCallLatencies, this.#timeToFirstChunk, this.#timeBetweenChunks, session.pairProgrammingMode);
737
+ this.#telemetryController.emitAgencticLoop_InvokeLLM(response.$metadata.requestId, conversationId, 'AgenticChatWithToolUse', toolNames ?? undefined, toolUseIds ?? undefined, 'Succeeded', this.#features.runtime.serverInfo.version ?? '', session.modelId, llmLatency, this.#toolCallLatencies, this.#timeToFirstChunk, this.#timeBetweenChunks, session.pairProgrammingMode, this.#abTestingAllocation?.experimentName, this.#abTestingAllocation?.userVariation);
708
738
  }
709
739
  else {
710
740
  // Send an error card to UI?
@@ -713,7 +743,7 @@ class AgenticChatController {
713
743
  status: codewhisperer_streaming_1.ToolResultStatus.ERROR,
714
744
  content: [{ text: result.error }],
715
745
  }));
716
- this.#telemetryController.emitAgencticLoop_InvokeLLM(response.$metadata.requestId, conversationId, 'AgenticChatWithToolUse', undefined, undefined, 'Failed', this.#features.runtime.serverInfo.version ?? '', session.modelId, llmLatency, this.#toolCallLatencies, this.#timeToFirstChunk, this.#timeBetweenChunks, session.pairProgrammingMode);
746
+ this.#telemetryController.emitAgencticLoop_InvokeLLM(response.$metadata.requestId, conversationId, 'AgenticChatWithToolUse', undefined, undefined, 'Failed', this.#features.runtime.serverInfo.version ?? '', session.modelId, llmLatency, this.#toolCallLatencies, this.#timeToFirstChunk, this.#timeBetweenChunks, session.pairProgrammingMode, this.#abTestingAllocation?.experimentName, this.#abTestingAllocation?.userVariation);
717
747
  if (result.error.startsWith('ToolUse input is invalid JSON:')) {
718
748
  content =
719
749
  'Your toolUse input is incomplete, try again. If the error happens consistently, break this task down into multiple tool uses with smaller input. Do not apologize.';
@@ -909,17 +939,20 @@ class AgenticChatController {
909
939
  cachedButtonBlockId = await chatResultStream.writeResultBlock(confirmationResult);
910
940
  const isExecuteBash = toolUse.name === 'executeBash';
911
941
  if (isExecuteBash) {
912
- this.#telemetryController.emitInteractWithAgenticChat('GeneratedCommand', tabId, session.pairProgrammingMode, session.getConversationType());
942
+ this.#telemetryController.emitInteractWithAgenticChat('GeneratedCommand', tabId, session.pairProgrammingMode, session.getConversationType(), this.#abTestingAllocation?.experimentName, this.#abTestingAllocation?.userVariation);
913
943
  }
914
944
  if (requiresAcceptance) {
915
945
  await this.waitForToolApproval(toolUse, chatResultStream, cachedButtonBlockId, session, toolUse.name);
916
946
  }
917
947
  if (isExecuteBash) {
918
- this.#telemetryController.emitInteractWithAgenticChat('RunCommand', tabId, session.pairProgrammingMode, session.getConversationType());
948
+ this.#telemetryController.emitInteractWithAgenticChat('RunCommand', tabId, session.pairProgrammingMode, session.getConversationType(), this.#abTestingAllocation?.experimentName, this.#abTestingAllocation?.userVariation);
919
949
  }
920
950
  }
921
951
  break;
922
952
  }
953
+ case qCodeReview_1.QCodeReview.toolName:
954
+ // no need to write tool message for code review
955
+ break;
923
956
  // — DEFAULT ⇒ Only MCP tools, but can also handle generic tool execution messages
924
957
  default:
925
958
  // Get original server and tool names from the mapping
@@ -969,6 +1002,22 @@ class AgenticChatController {
969
1002
  fileChange: { before: document?.getText() },
970
1003
  });
971
1004
  }
1005
+ if (toolUse.name === qCodeReview_1.QCodeReview.toolName) {
1006
+ try {
1007
+ let initialInput = JSON.parse(JSON.stringify(toolUse.input));
1008
+ let ruleArtifacts = await this.#additionalContextProvider.collectWorkspaceRules(tabId);
1009
+ if (ruleArtifacts !== undefined || ruleArtifacts !== null) {
1010
+ this.#features.logging.info(`RuleArtifacts: ${JSON.stringify(ruleArtifacts)}`);
1011
+ let pathsToRulesMap = ruleArtifacts.map(ruleArtifact => ({ path: ruleArtifact.id }));
1012
+ this.#features.logging.info(`PathsToRules: ${JSON.stringify(pathsToRulesMap)}`);
1013
+ initialInput['ruleArtifacts'] = pathsToRulesMap;
1014
+ }
1015
+ toolUse.input = initialInput;
1016
+ }
1017
+ catch (e) {
1018
+ this.#features.logging.warn(`could not parse QCodeReview tool input: ${e}`);
1019
+ }
1020
+ }
972
1021
  // After approval, add the path to the approved paths in the session
973
1022
  const inputPath = toolUse.input?.path || toolUse.input?.cwd;
974
1023
  if (inputPath) {
@@ -1033,9 +1082,23 @@ class AgenticChatController {
1033
1082
  fileChange: { ...cachedToolUse.fileChange, after: doc?.getText() },
1034
1083
  });
1035
1084
  }
1036
- this.#telemetryController.emitInteractWithAgenticChat('GeneratedDiff', tabId, session.pairProgrammingMode, session.getConversationType());
1085
+ this.#telemetryController.emitInteractWithAgenticChat('GeneratedDiff', tabId, session.pairProgrammingMode, session.getConversationType(), this.#abTestingAllocation?.experimentName, this.#abTestingAllocation?.userVariation);
1037
1086
  await chatResultStream.writeResultBlock(chatResult);
1038
1087
  break;
1088
+ case qCodeReview_1.QCodeReview.toolName:
1089
+ // no need to write tool result for code review, this is handled by model via chat
1090
+ // Push result in message so that it is picked by IDE plugin to show in issues panel
1091
+ const qCodeReviewResult = result;
1092
+ if (qCodeReviewResult?.output?.kind === 'json' &&
1093
+ qCodeReviewResult.output.success &&
1094
+ qCodeReviewResult.output.content?.findingsByFile) {
1095
+ await chatResultStream.writeResultBlock({
1096
+ type: 'tool',
1097
+ messageId: toolUse.toolUseId + qCodeReviewConstants_1.FINDINGS_MESSAGE_SUFFIX,
1098
+ body: qCodeReviewResult.output.content.findingsByFile,
1099
+ });
1100
+ }
1101
+ break;
1039
1102
  // — DEFAULT ⇒ MCP tools
1040
1103
  default:
1041
1104
  await this.#handleMcpToolResult(toolUse, result, session, chatResultStream);
@@ -1056,7 +1119,7 @@ class AgenticChatController {
1056
1119
  });
1057
1120
  }
1058
1121
  }
1059
- this.#telemetryController.emitToolUseSuggested(toolUse, session.conversationId ?? '', this.#features.runtime.serverInfo.version ?? '', latency, session.pairProgrammingMode);
1122
+ this.#telemetryController.emitToolUseSuggested(toolUse, session.conversationId ?? '', this.#features.runtime.serverInfo.version ?? '', latency, session.pairProgrammingMode, this.#abTestingAllocation?.experimentName, this.#abTestingAllocation?.userVariation);
1060
1123
  }
1061
1124
  }
1062
1125
  catch (err) {
@@ -1283,7 +1346,31 @@ class AgenticChatController {
1283
1346
  return undefined;
1284
1347
  }
1285
1348
  }
1349
+ #getToolOverWritableStream(chatResultStream, toolUse) {
1350
+ const toolMsgId = toolUse.toolUseId;
1351
+ return new WritableStream({
1352
+ write: async (chunk) => {
1353
+ if (this.#stoppedToolUses.has(toolMsgId))
1354
+ return;
1355
+ await chatResultStream.removeResultBlockAndUpdateUI(toolMsgId);
1356
+ await chatResultStream.writeResultBlock({
1357
+ type: 'tool',
1358
+ messageId: toolMsgId,
1359
+ body: chunk,
1360
+ });
1361
+ },
1362
+ close: async () => {
1363
+ if (this.#stoppedToolUses.has(toolMsgId))
1364
+ return;
1365
+ await chatResultStream.removeResultBlockAndUpdateUI(toolMsgId);
1366
+ this.#stoppedToolUses.add(toolMsgId);
1367
+ },
1368
+ });
1369
+ }
1286
1370
  #getWritableStream(chatResultStream, toolUse) {
1371
+ if (toolUse.name === qCodeReview_1.QCodeReview.toolName) {
1372
+ return this.#getToolOverWritableStream(chatResultStream, toolUse);
1373
+ }
1287
1374
  if (toolUse.name !== 'executeBash') {
1288
1375
  return;
1289
1376
  }
@@ -2900,6 +2987,40 @@ class AgenticChatController {
2900
2987
  body: (0, textFormatting_1.toolResultMessage)(toolUse, result),
2901
2988
  });
2902
2989
  }
2990
+ scheduleABTestingFetching(userContext) {
2991
+ if (!userContext) {
2992
+ return;
2993
+ }
2994
+ this.#abTestingFetchingTimeout = setInterval(() => {
2995
+ let codeWhispererServiceToken;
2996
+ try {
2997
+ codeWhispererServiceToken = AmazonQTokenServiceManager_1.AmazonQTokenServiceManager.getInstance().getCodewhispererService();
2998
+ }
2999
+ catch (error) {
3000
+ // getCodewhispererService only returns the cwspr client if the service manager was initialized
3001
+ // i.e. profile was selected otherwise it throws an error
3002
+ // we will not evaluate a/b status until profile is selected and service manager is fully initialized
3003
+ return;
3004
+ }
3005
+ // Clear interval once we have the CodewhispererService
3006
+ clearInterval(this.#abTestingFetchingTimeout);
3007
+ this.#abTestingFetchingTimeout = undefined;
3008
+ codeWhispererServiceToken
3009
+ .listFeatureEvaluations({ userContext })
3010
+ .then(result => {
3011
+ const feature = result.featureEvaluations?.find(feature => feature.feature === 'MaestroWorkspaceContext');
3012
+ if (feature) {
3013
+ this.#abTestingAllocation = {
3014
+ experimentName: feature.feature,
3015
+ userVariation: feature.variation,
3016
+ };
3017
+ }
3018
+ })
3019
+ .catch(error => {
3020
+ this.#features.logging.debug(`Error fetching AB testing result: ${error}`);
3021
+ });
3022
+ }, 5000);
3023
+ }
2903
3024
  #log(...messages) {
2904
3025
  this.#features.logging.log(messages.join(' '));
2905
3026
  }