Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Breaking Change",
"description": "Change keybind for focusing chat to ctrl+win+i on Windows, ctrl+cmd+i on macOS and ctrl+meta+i on Linux"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Feature",
"description": "Use inline chat to select code and transform it with natural language instructions"
}
24 changes: 19 additions & 5 deletions packages/amazonq/src/inlineChat/codeLenses/codeLenseProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

import * as vscode from 'vscode'
import * as os from 'os'
import { InlineTask, TaskState } from '../controller/inlineTask'

export class CodelensProvider implements vscode.CodeLensProvider {
Expand All @@ -27,7 +28,7 @@ export class CodelensProvider implements vscode.CodeLensProvider {
return
}
switch (task.state) {
case TaskState.InProgress:
case TaskState.InProgress: {
this.codeLenses = []
this.codeLenses.push(
new vscode.CodeLens(new vscode.Range(task.selectedRange.start, task.selectedRange.start), {
Expand All @@ -36,26 +37,39 @@ export class CodelensProvider implements vscode.CodeLensProvider {
})
)
break
case TaskState.WaitingForDecision:
}
case TaskState.WaitingForDecision: {
let acceptTitle: string
let rejectTitle: string
if (os.platform() === 'darwin') {
acceptTitle = 'Accept ($(newline))'
rejectTitle = `Reject ( \u238B )`
} else {
acceptTitle = 'Accept (Enter)'
rejectTitle = `Reject (Esc)`
}

this.codeLenses = []
this.codeLenses.push(
new vscode.CodeLens(new vscode.Range(task.selectedRange.start, task.selectedRange.start), {
title: 'Accept ($(newline))',
title: acceptTitle,
command: 'aws.amazonq.inline.waitForUserDecisionAcceptAll',
arguments: [task],
})
)
this.codeLenses.push(
new vscode.CodeLens(new vscode.Range(task.selectedRange.start, task.selectedRange.start), {
title: `Reject ( \u238B )`,
title: rejectTitle,
command: 'aws.amazonq.inline.waitForUserDecisionRejectAll',
arguments: [task],
})
)
break
default:
}
default: {
this.codeLenses = []
break
}
}
this._onDidChangeCodeLenses.fire()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ import { computeDecorations } from '../decorations/computeDecorations'
import { CodelensProvider } from '../codeLenses/codeLenseProvider'
import { ReferenceLogController } from 'aws-core-vscode/codewhispererChat'
import { CodeWhispererSettings } from 'aws-core-vscode/codewhisperer'
import { codicon, getIcon, getLogger, messages, setContext, Timeout } from 'aws-core-vscode/shared'
import { addEofNewline, codicon, getIcon, getLogger, messages, setContext, Timeout } from 'aws-core-vscode/shared'
import { InlineLineAnnotationController } from '../decorations/inlineLineAnnotationController'
import { fixEofNewline } from './utils'

export class InlineChatController {
private task: InlineTask | undefined
Expand Down Expand Up @@ -181,7 +180,7 @@ export class InlineChatController {
if (!query) {
return
}
await fixEofNewline(editor)
await addEofNewline(editor)
this.task = await this.createTask(query, editor.document, editor.selection)
await this.inlineLineAnnotationController.disable(editor)
await this.computeDiffAndRenderOnEditor(query, editor.document).catch(async (err) => {
Expand Down Expand Up @@ -357,46 +356,6 @@ export class InlineChatController {
}
}

// private async applyDiff(
// task: InlineTask,
// textDiff: TextDiff[],
// undoOption?: { undoStopBefore: boolean; undoStopAfter: boolean }
// ) {
// // const adjustedTextDiff = adjustTextDiffForEditing(textDiff)
// const visibleEditor = vscode.window.visibleTextEditors.find(
// (editor) => editor.document.uri === task.document.uri
// )
// const range = task.newSelectedRange ?? task.selectedRange
// const newRange = new vscode.Range(
// range!.start,
// new vscode.Position(range.start.line + task.estimatedResponse!.split('\n').length - 1, 0)
// )
// task.newSelectedRange = newRange
// if (visibleEditor) {
// await visibleEditor.edit(
// (editBuilder) => {
// editBuilder.replace(range, task.estimatedResponse!)
// },
// undoOption ?? { undoStopBefore: true, undoStopAfter: false }
// )
// } else {
// // if (previousDiff) {
// // const edit = new vscode.WorkspaceEdit()
// // for (const insertion of previousDiff) {
// // edit.delete(task.document.uri, insertion.range)
// // }
// // await vscode.workspace.applyEdit(edit)
// // }
// // const edit = new vscode.WorkspaceEdit()
// // for (const change of textDiff) {
// // if (change.type === 'insertion') {
// // edit.insert(task.document.uri, change.range.start, change.replacementText)
// // }
// // }
// // await vscode.workspace.applyEdit(edit)
// }
// }

private undoListener(task: InlineTask) {
const listener: vscode.Disposable = vscode.workspace.onDidChangeTextDocument(async (event) => {
const { document, contentChanges } = event
Expand Down
2 changes: 1 addition & 1 deletion packages/amazonq/src/inlineChat/controller/inlineTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import type { CodeReference } from 'aws-core-vscode/amazonq'
import type { InlineChatEvent } from 'aws-core-vscode/codewhisperer'
import type { Decorations } from '../decorations/inlineDecorator'
import { computeDecorations } from '../decorations/computeDecorations'
import { expandSelectionToFullLines } from './utils'
import { extractLanguageNameFromFile } from 'aws-core-vscode/codewhispererChat'
import { expandSelectionToFullLines } from 'aws-core-vscode/shared'

interface TextToInsert {
type: 'insertion'
Expand Down
35 changes: 0 additions & 35 deletions packages/amazonq/src/inlineChat/controller/utils.ts

This file was deleted.

18 changes: 18 additions & 0 deletions packages/amazonq/src/inlineChat/output/responseTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import { getLogger } from 'aws-core-vscode/shared'
import { decode } from 'he'
import { InlineTask } from '../controller/inlineTask'

/**
* Transforms the response from the INLINE_CHAT GenerateAssistantResponse call.
*
* @param response - The raw response string from GenerateAssistantResponse.
* @param inlineTask - The inline task object containing information about the current task.
* @param isWholeResponse - A boolean indicating whether this is a complete response or a partial one.
* @returns The decoded response string, or undefined if an error occurs.
*/
export function responseTransformer(
response: string,
inlineTask: InlineTask,
Expand All @@ -28,6 +36,16 @@ export function responseTransformer(
}
}

/**
* This function is used to handle partial responses in inline tasks. It divides
* the selected text into two parts:
* 1. The "left" part, which contains the same number of lines as the response.
* 2. The "right" part, which contains the remaining lines.
*
* @param response - The response string from the assistant.
* @param inlineTask - The inline task object containing the full selected text.
* @returns A tuple with two strings: [leftPart, rightPart].
*/
function extractPartialCode(response: string, inlineTask: InlineTask): [string, string] {
const lineCount = response.split('\n').length
const splitLines = inlineTask.selectedText.split('\n')
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/amazonq/util/authUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
import { FeatureAuthState } from '../../codewhisperer'
import { AuthFollowUpType, AuthMessageDataMap } from '../auth/model'

/**
* This function evaluates the authentication state of CodeWhisperer features (chat and core)
* when the authentication is not valid, and returns the appropriate authentication follow-up type and message.
*
* @param credentialState - The current authentication state for each CodeWhisperer feature
* @returns An object containing:
* - authType: The type of authentication follow-up required (AuthFollowUpType)
* - message: The corresponding message for the determined auth type
*/
export function extractAuthFollowUp(credentialState: FeatureAuthState) {
let authType: AuthFollowUpType = 'full-auth'
let message = AuthMessageDataMap[authType].message
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/codewhisperer/client/codewhisperer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ export class DefaultCodeWhispererClient {
const client = await this.createUserSdkClient()
const requester = async (request: CodeWhispererUserClient.ListAvailableCustomizationsRequest) =>
client.listAvailableCustomizations(request).promise()
// @ts-ignore
return pageableToCollection(requester, {}, 'nextToken')
.promise()
.then((resps) => {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/shared/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ export { CrashMonitoring } from './crashMonitoring'
export { amazonQDiffScheme } from './constants'
export * from './featureConfig'
export * from './icons'
export * from './utilities/textDocumentUtilities'
31 changes: 31 additions & 0 deletions packages/core/src/shared/utilities/textDocumentUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,34 @@ export async function showFile(uri: vscode.Uri) {
await vscode.window.showTextDocument(doc, { preview: false })
await vscode.languages.setTextDocumentLanguage(doc, 'log')
}

/**
* Expands the given selection to full line(s) in the document.
* If the selection is partial, it will be extended to include the entire line(s).
* @param document The current text document
* @param selection The current selection
* @returns A new Range that covers full line(s) of the selection
*/
export function expandSelectionToFullLines(document: vscode.TextDocument, selection: vscode.Selection): vscode.Range {
const startLine = document.lineAt(selection.start.line)
const endLine = document.lineAt(selection.end.line)
return new vscode.Range(startLine.range.start, endLine.range.end)
}

/**
* Ensures the document ends with a newline character.
* If the selection is at the end of the last line and the document doesn't end with a newline,
* this function inserts one.
* @param editor The VS Code text editor to modify
*/
export async function addEofNewline(editor: vscode.TextEditor) {
if (
editor.selection.end.line === editor.document.lineCount - 1 &&
editor.selection.end.character === editor.document.lineAt(editor.selection.end.line).text.length &&
!editor.document.getText().endsWith('\n')
) {
await editor.edit((editBuilder) => {
editBuilder.insert(editor.selection.end, '\n')
})
}
}
Loading