Skip to content

Commit f4dc301

Browse files
Merge master into feature/agentic-chat
2 parents eed4803 + 8af52de commit f4dc301

File tree

30 files changed

+5470
-4688
lines changed

30 files changed

+5470
-4688
lines changed

package-lock.json

Lines changed: 2609 additions & 2285 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/amazonq/src/lsp/client.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,7 @@ export async function startLanguageServer(
9393
const auth = new AmazonQLspAuth(client)
9494

9595
return client.onReady().then(async () => {
96-
await auth.init()
97-
const inlineManager = new InlineCompletionManager(client)
98-
inlineManager.registerInlineCompletion()
99-
if (Experiments.instance.get('amazonqChatLSP', false)) {
100-
activate(client, encryptionKey, resourcePaths.mynahUI)
101-
}
102-
103-
// Request handler for when the server wants to know about the clients auth connnection
96+
// Request handler for when the server wants to know about the clients auth connnection. Must be registered before the initial auth init call
10497
client.onRequest<ConnectionMetadata, Error>(notificationTypes.getConnectionMetadata.method, () => {
10598
return {
10699
sso: {
@@ -109,6 +102,13 @@ export async function startLanguageServer(
109102
}
110103
})
111104

105+
await auth.init()
106+
const inlineManager = new InlineCompletionManager(client)
107+
inlineManager.registerInlineCompletion()
108+
if (Experiments.instance.get('amazonqChatLSP', false)) {
109+
activate(client, encryptionKey, resourcePaths.mynahUI)
110+
}
111+
112112
// Temporary code for pen test. Will be removed when we switch to the real flare auth
113113
const authInterval = setInterval(async () => {
114114
try {

packages/core/package.json

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -497,41 +497,41 @@
497497
"dependencies": {
498498
"@amzn/amazon-q-developer-streaming-client": "file:../../src.gen/@amzn/amazon-q-developer-streaming-client",
499499
"@amzn/codewhisperer-streaming": "file:../../src.gen/@amzn/codewhisperer-streaming",
500-
"@aws-sdk/client-api-gateway": "<3.696.0",
501-
"@aws-sdk/client-apprunner": "<3.696.0",
502-
"@aws-sdk/client-cloudcontrol": "<3.696.0",
503-
"@aws-sdk/client-cloudformation": "<3.696.0",
504-
"@aws-sdk/client-cloudwatch-logs": "<3.696.0",
505-
"@aws-sdk/client-codecatalyst": "<3.696.0",
506-
"@aws-sdk/client-cognito-identity": "<3.696.0",
507-
"@aws-sdk/client-docdb": "<3.696.0",
508-
"@aws-sdk/client-docdb-elastic": "<3.696.0",
509-
"@aws-sdk/client-ec2": "<3.696.0",
510-
"@aws-sdk/client-iam": "<3.696.0",
511-
"@aws-sdk/client-lambda": "<3.696.0",
512-
"@aws-sdk/client-s3": "<3.696.0",
513-
"@aws-sdk/client-ssm": "<3.696.0",
514-
"@aws-sdk/client-sso": "<3.696.0",
515-
"@aws-sdk/client-sso-oidc": "<3.696.0",
516-
"@aws-sdk/credential-provider-env": "<3.696.0",
517-
"@aws-sdk/credential-provider-process": "<3.696.0",
518-
"@aws-sdk/credential-provider-sso": "<3.696.0",
519-
"@aws-sdk/lib-storage": "<3.696.0",
520-
"@aws-sdk/property-provider": "<3.696.0",
521-
"@aws-sdk/protocol-http": "<3.696.0",
522-
"@aws-sdk/s3-request-presigner": "<3.696.0",
523-
"@aws-sdk/smithy-client": "<3.696.0",
524-
"@aws-sdk/util-arn-parser": "<3.696.0",
500+
"@aws-sdk/client-api-gateway": "<3.731.0",
501+
"@aws-sdk/client-cloudcontrol": "<3.731.0",
502+
"@aws-sdk/client-cloudformation": "<3.731.0",
503+
"@aws-sdk/client-cloudwatch-logs": "<3.731.0",
504+
"@aws-sdk/client-codecatalyst": "<3.731.0",
505+
"@aws-sdk/client-cognito-identity": "<3.731.0",
506+
"@aws-sdk/client-docdb": "<3.731.0",
507+
"@aws-sdk/client-docdb-elastic": "<3.731.0",
508+
"@aws-sdk/client-ec2": "<3.731.0",
509+
"@aws-sdk/client-iam": "<3.731.0",
510+
"@aws-sdk/client-lambda": "<3.731.0",
511+
"@aws-sdk/client-s3": "<3.731.0",
512+
"@aws-sdk/client-ssm": "<3.731.0",
513+
"@aws-sdk/client-sso": "<3.731.0",
514+
"@aws-sdk/client-sso-oidc": "<3.731.0",
515+
"@aws-sdk/client-apprunner": "<3.731.0",
516+
"@aws-sdk/credential-provider-env": "<3.731.0",
517+
"@aws-sdk/credential-provider-process": "<3.731.0",
518+
"@aws-sdk/credential-provider-sso": "<3.731.0",
519+
"@aws-sdk/lib-storage": "<3.731.0",
520+
"@aws-sdk/property-provider": "<3.731.0",
521+
"@aws-sdk/protocol-http": "<3.731.0",
522+
"@aws-sdk/s3-request-presigner": "<3.731.0",
523+
"@aws-sdk/smithy-client": "<3.731.0",
524+
"@aws-sdk/util-arn-parser": "<3.731.0",
525525
"@aws/mynah-ui": "^4.26.1",
526526
"@gerhobbelt/gitignore-parser": "^0.2.0-9",
527527
"@iarna/toml": "^2.2.5",
528-
"@smithy/fetch-http-handler": "^3.0.0",
529-
"@smithy/middleware-retry": "^3.0.0",
530-
"@smithy/node-http-handler": "^3.0.0",
531-
"@smithy/protocol-http": "^4.0.0",
532-
"@smithy/service-error-classification": "^3.0.0",
533-
"@smithy/shared-ini-file-loader": "^3.0.0",
534-
"@smithy/util-retry": "^3.0.0",
528+
"@smithy/fetch-http-handler": "^5.0.1",
529+
"@smithy/middleware-retry": "^4.0.3",
530+
"@smithy/node-http-handler": "^4.0.2",
531+
"@smithy/protocol-http": "^5.0.1",
532+
"@smithy/service-error-classification": "^4.0.1",
533+
"@smithy/shared-ini-file-loader": "^4.0.0",
534+
"@smithy/util-retry": "^4.0.1",
535535
"@vscode/debugprotocol": "^1.57.0",
536536
"@zip.js/zip.js": "^2.7.41",
537537
"adm-zip": "^0.5.10",

packages/core/src/amazonqDoc/controllers/chat/controller.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
SelectedFolderNotInWorkspaceFolderError,
3131
WorkspaceFolderNotFoundError,
3232
createUserFacingErrorMessage,
33+
getMetricResult,
3334
} from '../../../amazonqFeatureDev/errors'
3435
import { BaseChatSessionStorage } from '../../../amazonq/commons/baseChatStorage'
3536
import { DocMessenger } from '../../messenger'
@@ -44,8 +45,8 @@ import {
4445
import { getPathsFromZipFilePath, SvgFileExtension } from '../../../amazonq/util/files'
4546
import { FollowUpTypes } from '../../../amazonq/commons/types'
4647
import { DocGenerationTask, DocGenerationTasks } from '../docGenerationTask'
47-
import { DevPhase } from '../../types'
4848
import { normalize } from '../../../shared/utilities/pathUtils'
49+
import { DevPhase, MetricDataOperationName, MetricDataResult } from '../../types'
4950

5051
export interface ChatControllerEventEmitters {
5152
readonly processHumanChatMessage: EventEmitter<any>
@@ -557,6 +558,7 @@ export class DocController {
557558
await session.preloader(message)
558559

559560
try {
561+
await session.sendDocMetricData(MetricDataOperationName.StartDocGeneration, MetricDataResult.Success)
560562
await session.send(message, docGenerationTask.mode, docGenerationTask.folderPath)
561563
const filePaths = session.state.filePaths ?? []
562564
const deletedFiles = session.state.deletedFiles ?? []
@@ -627,6 +629,10 @@ export class DocController {
627629

628630
await session.sendDocTelemetryEvent(docGenerationEvent, 'generation')
629631
}
632+
} catch (err: any) {
633+
getLogger().error(`${featureName}: Error during doc generation: ${err}`)
634+
await session.sendDocMetricData(MetricDataOperationName.EndDocGeneration, getMetricResult(err))
635+
throw err
630636
} finally {
631637
if (session?.state?.tokenSource?.token.isCancellationRequested) {
632638
await this.newTask({ tabID })
@@ -636,6 +642,7 @@ export class DocController {
636642
this.messenger.sendChatInputEnabled(tabID, false)
637643
}
638644
}
645+
await session.sendDocMetricData(MetricDataOperationName.EndDocGeneration, MetricDataResult.Success)
639646
}
640647

641648
private authClicked(message: any) {

packages/core/src/amazonqDoc/errors.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,60 +3,60 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { ToolkitError } from '../shared/errors'
6+
import { ClientError, ContentLengthError as CommonContentLengthError } from '../shared/errors'
77
import { i18n } from '../shared/i18n-helper'
88

9-
export class DocServiceError extends ToolkitError {
9+
export class DocClientError extends ClientError {
1010
remainingIterations?: number
1111
constructor(message: string, code: string, remainingIterations?: number) {
1212
super(message, { code })
1313
this.remainingIterations = remainingIterations
1414
}
1515
}
1616

17-
export class ReadmeTooLargeError extends DocServiceError {
17+
export class ReadmeTooLargeError extends DocClientError {
1818
constructor() {
1919
super(i18n('AWS.amazonq.doc.error.readmeTooLarge'), ReadmeTooLargeError.name)
2020
}
2121
}
2222

23-
export class ReadmeUpdateTooLargeError extends DocServiceError {
23+
export class ReadmeUpdateTooLargeError extends DocClientError {
2424
constructor(remainingIterations: number) {
2525
super(i18n('AWS.amazonq.doc.error.readmeUpdateTooLarge'), ReadmeUpdateTooLargeError.name, remainingIterations)
2626
}
2727
}
2828

29-
export class WorkspaceEmptyError extends DocServiceError {
29+
export class WorkspaceEmptyError extends DocClientError {
3030
constructor() {
3131
super(i18n('AWS.amazonq.doc.error.workspaceEmpty'), WorkspaceEmptyError.name)
3232
}
3333
}
3434

35-
export class NoChangeRequiredException extends DocServiceError {
35+
export class NoChangeRequiredException extends DocClientError {
3636
constructor() {
3737
super(i18n('AWS.amazonq.doc.error.noChangeRequiredException'), NoChangeRequiredException.name)
3838
}
3939
}
4040

41-
export class PromptRefusalException extends DocServiceError {
41+
export class PromptRefusalException extends DocClientError {
4242
constructor(remainingIterations: number) {
4343
super(i18n('AWS.amazonq.doc.error.promptRefusal'), PromptRefusalException.name, remainingIterations)
4444
}
4545
}
4646

47-
export class ContentLengthError extends DocServiceError {
47+
export class ContentLengthError extends CommonContentLengthError {
4848
constructor() {
49-
super(i18n('AWS.amazonq.doc.error.contentLengthError'), ContentLengthError.name)
49+
super(i18n('AWS.amazonq.doc.error.contentLengthError'), { code: ContentLengthError.name })
5050
}
5151
}
5252

53-
export class PromptTooVagueError extends DocServiceError {
53+
export class PromptTooVagueError extends DocClientError {
5454
constructor(remainingIterations: number) {
5555
super(i18n('AWS.amazonq.doc.error.promptTooVague'), PromptTooVagueError.name, remainingIterations)
5656
}
5757
}
5858

59-
export class PromptUnrelatedError extends DocServiceError {
59+
export class PromptUnrelatedError extends DocClientError {
6060
constructor(remainingIterations: number) {
6161
super(i18n('AWS.amazonq.doc.error.promptUnrelated'), PromptUnrelatedError.name, remainingIterations)
6262
}

packages/core/src/amazonqDoc/session/session.ts

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ import { FeatureDevClient } from '../../amazonqFeatureDev/client/featureDev'
1414
import { TelemetryHelper } from '../../amazonq/util/telemetryHelper'
1515
import { ConversationNotStartedState } from '../../amazonqFeatureDev/session/sessionState'
1616
import { logWithConversationId } from '../../amazonqFeatureDev/userFacingText'
17-
import { ConversationIdNotFoundError } from '../../amazonqFeatureDev/errors'
17+
import { ConversationIdNotFoundError, IllegalStateError } from '../../amazonqFeatureDev/errors'
1818
import { referenceLogText } from '../../amazonqFeatureDev/constants'
1919
import {
2020
DocInteractionType,
2121
DocV2AcceptanceEvent,
2222
DocV2GenerationEvent,
2323
SendTelemetryEventRequest,
24+
MetricData,
2425
} from '../../codewhisperer/client/codewhispereruserclient'
2526
import { getClientId, getOperatingSystem, getOptOutPreference } from '../../shared/telemetry/util'
2627
import { DocMessenger } from '../messenger'
@@ -72,7 +73,7 @@ export class Session {
7273

7374
get state() {
7475
if (!this._state) {
75-
throw new Error("State should be initialized before it's read")
76+
throw new IllegalStateError("State should be initialized before it's read")
7677
}
7778
return this._state
7879
}
@@ -269,15 +270,40 @@ export class Session {
269270
return { leftPath, rightPath, ...diff }
270271
}
271272

273+
public async sendDocMetricData(operationName: string, result: string) {
274+
const metricData = {
275+
metricName: 'Operation',
276+
metricValue: 1,
277+
timestamp: new Date(),
278+
product: 'DocGeneration',
279+
dimensions: [
280+
{
281+
name: 'operationName',
282+
value: operationName,
283+
},
284+
{
285+
name: 'result',
286+
value: result,
287+
},
288+
],
289+
}
290+
await this.sendDocTelemetryEvent(metricData, 'metric')
291+
}
292+
272293
public async sendDocTelemetryEvent(
273-
telemetryEvent: DocV2GenerationEvent | DocV2AcceptanceEvent,
274-
eventType: 'generation' | 'acceptance'
294+
telemetryEvent: DocV2GenerationEvent | DocV2AcceptanceEvent | MetricData,
295+
eventType: 'generation' | 'acceptance' | 'metric'
275296
) {
276297
const client = await this.proxyClient.getClient()
298+
const telemetryEventKey = {
299+
generation: 'docV2GenerationEvent',
300+
acceptance: 'docV2AcceptanceEvent',
301+
metric: 'metricData',
302+
}[eventType]
277303
try {
278304
const params: SendTelemetryEventRequest = {
279305
telemetryEvent: {
280-
[eventType === 'generation' ? 'docV2GenerationEvent' : 'docV2AcceptanceEvent']: telemetryEvent,
306+
[telemetryEventKey]: telemetryEvent,
281307
},
282308
optOutPreference: getOptOutPreference(),
283309
userContext: {
@@ -290,14 +316,23 @@ export class Session {
290316
}
291317

292318
const response = await client.sendTelemetryEvent(params).promise()
293-
getLogger().debug(
294-
`${featureName}: successfully sent docV2${eventType === 'generation' ? 'GenerationEvent' : 'AcceptanceEvent'}: ConversationId: ${telemetryEvent.conversationId} RequestId: ${response.$response.requestId}`
295-
)
319+
if (eventType === 'metric') {
320+
getLogger().debug(
321+
`${featureName}: successfully sent metricData: RequestId: ${response.$response.requestId}`
322+
)
323+
} else {
324+
getLogger().debug(
325+
`${featureName}: successfully sent docV2${eventType === 'generation' ? 'GenerationEvent' : 'AcceptanceEvent'}: ` +
326+
`ConversationId: ${(telemetryEvent as DocV2GenerationEvent | DocV2AcceptanceEvent).conversationId} ` +
327+
`RequestId: ${response.$response.requestId}`
328+
)
329+
}
296330
} catch (e) {
331+
const error = e as Error
332+
const eventTypeString = eventType === 'metric' ? 'metricData' : `doc ${eventType}`
297333
getLogger().error(
298-
`${featureName}: failed to send doc ${eventType} telemetry: ${(e as Error).name}: ${
299-
(e as Error).message
300-
} RequestId: ${(e as any).requestId}`
334+
`${featureName}: failed to send ${eventTypeString} telemetry: ${error.name}: ${error.message} ` +
335+
`RequestId: ${(e as any).$response?.requestId}`
301336
)
302337
}
303338
}
@@ -308,7 +343,7 @@ export class Session {
308343

309344
get uploadId() {
310345
if (!('uploadId' in this.state)) {
311-
throw new Error("UploadId has to be initialized before it's read")
346+
throw new IllegalStateError("UploadId has to be initialized before it's read")
312347
}
313348
return this.state.uploadId
314349
}

0 commit comments

Comments
 (0)