Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
jpinkney-aws committed Dec 16, 2024
2 parents 86a6e6e + a4c3443 commit e1c4635
Show file tree
Hide file tree
Showing 78 changed files with 1,115 additions and 264 deletions.
5 changes: 5 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ module.exports = {
name: 'fs',
message: 'Avoid node:fs and use shared/fs/fs.ts when possible.',
},
{
name: 'child_process',
message:
'Avoid child_process, use ChildProcess from `shared/utilities/processUtils.ts` instead.',
},
],
},
],
Expand Down
2 changes: 1 addition & 1 deletion buildspec/linuxE2ETests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ phases:
commands:
- export HOME=/home/codebuild-user
# Ignore failure until throttling issues are fixed.
- xvfb-run npm run testE2E || true
- xvfb-run npm run testE2E
- VCS_COMMIT_ID="${CODEBUILD_RESOLVED_SOURCE_VERSION}"
- CI_BUILD_URL=$(echo $CODEBUILD_BUILD_URL | sed 's/#/%23/g')
- CI_BUILD_ID="${CODEBUILD_BUILD_ID}"
Expand Down
103 changes: 102 additions & 1 deletion docs/arch_develop.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ await tester.result(items[0].data) // Execute the actions, asserting the final r

Abstractly, a 'wizard' is a collection of discrete, linear steps (subroutines), where each step can potentially be dependent on prior steps, that results in some final state. Wizards are extremely common in top-level flows such as creating a new resource, deployments, or confirmation messages. For these kinds of flows, we have a shared `Wizard` class that handles the bulk of control flow and state management logic for us.

### Creating a Wizard (Quick Picks)
### 1. `Wizard` Class

Create a new wizard by extending the base `Wizard` class, using the template type to specify the
shape of the wizard state. All wizards have an internal `form` property that is used to assign
Expand Down Expand Up @@ -482,6 +482,41 @@ class ExampleWizard extends Wizard<ExampleState> {
}
```

### 2. `CompositeWizard` Class

`CompositeWizard` extends `Wizard` to create and manage a collection of nested/child wizards.

Extend this class to create a wizard that contains other wizards as part of a prompter flow.
Use `this.createWizardPrompter()` to use a wizard as a prompter in the `CompositeWizard`.

Example:

```ts

// Child wizard
class ChildWizard extends Wizard<ChildWizardForm> {...}


// Composite wizard
interface SingleNestedWizardForm {
...
singleNestedWizardNestedProp: string
...
}

class SingleNestedWizard extends CompositeWizard<SingleNestedWizardForm> {
constructor() {
super()
...
this.form.singleNestedWizardNestedProp.bindPrompter(() =>
this.createWizardPrompter<ChildWizard, ChildWizardForm>(ChildWizard)
)
...
}
}

```

### Executing

Wizards can be ran by calling the async `run` method:
Expand All @@ -495,6 +530,8 @@ Note that all wizards can potentially return `undefined` if the workflow was can

### Testing

#### Using `WizardTester`

Use `createWizardTester` on an instance of a wizard. Tests can then be constructed by asserting both the user-defined and internal state. Using the above `ExampleWizard`:

```ts
Expand All @@ -505,6 +542,70 @@ tester.foo.applyInput('Hello, world!') // Manipulate 'user' state
tester.bar.assertShow() // True since 'foo' has a defined value
```

#### Using `PrompterTester`

Use `PrompterTester` to simulate user behavior (click, input and selection) on prompters to test end-to-end flow of a wizard.

Example:

```ts
// 1. Register PrompterTester handlers
const prompterTester = PrompterTester.init()
.handleInputBox('Input Prompter title 1', (inputBox) => {
// Register Input Prompter handler
inputBox.acceptValue('my-source-bucket-name')
})
.handleQuickPick('Quick Pick Prompter title 2', (quickPick) => {
// Register Quick Pick Prompter handler

// Optional assertion can be added as part of the handler function
assert.strictEqual(quickPick.items.length, 2)
assert.strictEqual(quickPick.items[0].label, 'Specify required parameters and save as defaults')
assert.strictEqual(quickPick.items[1].label, 'Specify required parameters')
// Choose item
quickPick.acceptItem(quickPick.items[0])
})
.handleQuickPick(
'Quick Pick Prompter with various handler behavior title 3',
(() => {
// Register handler with dynamic behavior
const generator = (function* () {
// First call, choose '**'
yield async (picker: TestQuickPick) => {
await picker.untilReady()
assert.strictEqual(picker.items[1].label, '**')
picker.acceptItem(picker.items[1])
}
// Second call, choose BACK button
yield async (picker: TestQuickPick) => {
await picker.untilReady()
picker.pressButton(vscode.QuickInputButtons.Back)
}
// Third and subsequent call
while (true) {
yield async (picker: TestQuickPick) => {
await picker.untilReady()
picker.acceptItem(picker.items[1])
}
}
})()

return (picker: TestQuickPick) => {
const next = generator.next().value
return next(picker)
}
})()
)
.build()

// 2. Run your wizard class
const result = await wizard.run()

// 3. Assert your tests
prompterTester.assertCallAll()
prompterTester.assertCallOrder('Input Prompter title 1', 1)
```

## Module path debugging

Node has an environment variable `NODE_DEBUG=module` that helps to debug module imports. This can be helpful on windows, which can load node modules into uppercase or lower case drive letters, depending on the drive letter of the parent module.
Expand Down
20 changes: 10 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"generateNonCodeFiles": "npm run generateNonCodeFiles -w packages/ --if-present"
},
"devDependencies": {
"@aws-toolkits/telemetry": "^1.0.287",
"@aws-toolkits/telemetry": "^1.0.289",
"@playwright/browser-chromium": "^1.43.1",
"@stylistic/eslint-plugin": "^2.11.0",
"@types/he": "^1.2.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Bug Fix",
"description": "/review: Apply fix removes other issues in the same file."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Bug Fix",
"description": "Fix(Amazon Q Code Transformation): show correct diff when running consecutive transformations"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Bug Fix",
"description": "Improve when the welcome page is shown in amazon q chat"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Bug Fix",
"description": "Chat: When navigating to previous prompts, code attachments are sometimes displayed incorrectly"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Bug Fix",
"description": "Chat: When writing a prompt without sending it, navigating via up/down arrows sometimes deletes the unsent prompt."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Feature",
"description": "Chat: improve font size and line-height in footer (below prompt input field)"
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ describe('crossFileContextUtil', function () {
assert.strictEqual(actual.supplementalContextItems[3].content.split('\n').length, 50)
})

it('for t2 group, should return global bm25 context and no repomap', async function () {
it.skip('for t2 group, should return global bm25 context and no repomap', async function () {
await toTextEditor(aStringWithLineCount(200), 'CrossFile.java', tempFolder, { preview: false })
const myCurrentEditor = await toTextEditor('', 'TargetFile.java', tempFolder, {
preview: false,
Expand Down
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,8 @@
"dependencies": {
"@amzn/amazon-q-developer-streaming-client": "file:../../src.gen/@amzn/amazon-q-developer-streaming-client",
"@amzn/codewhisperer-streaming": "file:../../src.gen/@amzn/codewhisperer-streaming",
"@aws-sdk/client-cloudwatch-logs": "^3.666.0",
"@aws-sdk/client-cloudformation": "^3.667.0",
"@aws-sdk/client-cloudwatch-logs": "^3.666.0",
"@aws-sdk/client-cognito-identity": "^3.637.0",
"@aws-sdk/client-lambda": "^3.637.0",
"@aws-sdk/client-sso": "^3.342.0",
Expand All @@ -510,7 +510,7 @@
"@aws-sdk/property-provider": "3.46.0",
"@aws-sdk/smithy-client": "^3.46.0",
"@aws-sdk/util-arn-parser": "^3.46.0",
"@aws/mynah-ui": "^4.21.0",
"@aws/mynah-ui": "^4.21.2",
"@gerhobbelt/gitignore-parser": "^0.2.0-9",
"@iarna/toml": "^2.2.5",
"@smithy/middleware-retry": "^2.3.1",
Expand Down
6 changes: 3 additions & 3 deletions packages/core/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"AWS.configuration.description.suppressPrompts": "Prompts which ask for confirmation. Checking an item suppresses the prompt.",
"AWS.configuration.enableCodeLenses": "Enable SAM hints in source code and template.yaml files",
"AWS.configuration.description.resources.enabledResources": "AWS resources to display in the 'Resources' portion of the explorer.",
"AWS.configuration.description.experiments": "Try experimental features and give feedback. Note that experimental features may be removed at any time.\n * `jsonResourceModification` - Enables basic create, update, and delete support for cloud resources via the JSON Resources explorer component.\n * `samSyncCode` - Adds an additional code-only option when synchronizing SAM applications. Code-only synchronizations are faster but can cause drift in the CloudFormation stack. Does nothing when using the legacy SAM deploy feature.\n * `iamPolicyChecks` - Enables IAM Policy Checks feature, allowing users to validate IAM policies against IAM policy grammar, AWS best practices, and specified security standards.",
"AWS.configuration.description.experiments": "Try experimental features and give feedback. Note that experimental features may be removed at any time.\n * `jsonResourceModification` - Enables basic create, update, and delete support for cloud resources via the JSON Resources explorer component.\n * `ec2RemoteConnect` - Allows interfacing with EC2 instances with options to start, stop, and establish remote connections. Remote connections are done over SSM and can be through a terminal or a remote VSCode window.",
"AWS.stepFunctions.asl.format.enable.desc": "Enables the default formatter used with Amazon States Language files",
"AWS.stepFunctions.asl.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons).",
"AWS.configuration.description.awssam.debug.api": "API Gateway configuration",
Expand Down Expand Up @@ -142,8 +142,8 @@
"AWS.command.refreshAwsExplorer": "Refresh Explorer",
"AWS.command.refreshCdkExplorer": "Refresh CDK Explorer",
"AWS.command.cdk.help": "View CDK Documentation",
"AWS.command.ec2.openTerminal": "Open terminal to EC2 instance...",
"AWS.command.ec2.openRemoteConnection": "Connect to EC2 instance in New Window...",
"AWS.command.ec2.openTerminal": "Open Terminal to EC2 Instance...",
"AWS.command.ec2.openRemoteConnection": "Connect VS Code to EC2 Instance...",
"AWS.command.ec2.startInstance": "Start EC2 Instance",
"AWS.command.ec2.linkToLaunch": "Launch EC2 Instance",
"AWS.command.ec2.stopInstance": "Stop EC2 Instance",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/scripts/build/generateServiceClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import * as proc from 'child_process'
import * as proc from 'child_process' // eslint-disable-line no-restricted-imports
import * as nodefs from 'fs' // eslint-disable-line no-restricted-imports
import * as path from 'path'

Expand Down
2 changes: 1 addition & 1 deletion packages/core/scripts/test/launchTestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import * as proc from 'child_process'
import * as proc from 'child_process' // eslint-disable-line no-restricted-imports
import packageJson from '../../package.json'
import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath } from '@vscode/test-electron'
import { join, resolve } from 'path'
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/amazonq/lsp/lspClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import * as vscode from 'vscode'
import * as path from 'path'
import * as nls from 'vscode-nls'
import * as cp from 'child_process'
import { spawn } from 'child_process' // eslint-disable-line no-restricted-imports
import * as crypto from 'crypto'
import * as jose from 'jose'

Expand Down Expand Up @@ -199,7 +199,7 @@ export async function activate(extensionContext: ExtensionContext) {

const nodename = process.platform === 'win32' ? 'node.exe' : 'node'

const child = cp.spawn(extensionContext.asAbsolutePath(path.join('resources', nodename)), [
const child = spawn(extensionContext.asAbsolutePath(path.join('resources', nodename)), [
serverModule,
...debugOptions.execArgv,
])
Expand Down
3 changes: 0 additions & 3 deletions packages/core/src/amazonq/lsp/lspController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,6 @@ export class LspController extends LspDownloader {
})
} finally {
this._isIndexingInProgress = false
const repomapFile = await LspClient.instance.getRepoMapJSON()
// console.log(repomapFile)
getLogger().info(`File path ${repomapFile}`)
}
}

Expand Down
10 changes: 6 additions & 4 deletions packages/core/src/amazonq/webview/generators/webViewContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class WebViewContentGenerator {
return JSON.stringify(Array.from(featureConfigs.entries()))
}

public async generate(extensionURI: Uri, webView: Webview, showWelcomePage: boolean): Promise<string> {
public async generate(extensionURI: Uri, webView: Webview): Promise<string> {
const entrypoint = process.env.WEBPACK_DEVELOPER_SERVER
? 'http: localhost'
: 'https: file+.vscode-resources.vscode-cdn.net'
Expand All @@ -47,14 +47,14 @@ export class WebViewContentGenerator {
<head>
<meta http-equiv="Content-Security-Policy" content="${contentPolicy}">
<title>Amazon Q (Preview)</title>
${await this.generateJS(extensionURI, webView, showWelcomePage)}
${await this.generateJS(extensionURI, webView)}
</head>
<body ${featureDataAttributes}>
</body>
</html>`
}

private async generateJS(extensionURI: Uri, webView: Webview, showWelcomePage: boolean): Promise<string> {
private async generateJS(extensionURI: Uri, webView: Webview): Promise<string> {
const source = path.join('vue', 'src', 'amazonq', 'webview', 'ui', 'amazonq-ui.js') // Sent to dist/vue folder in webpack.
const assetsPath = Uri.joinPath(extensionURI)
const javascriptUri = Uri.joinPath(assetsPath, 'dist', source)
Expand All @@ -80,14 +80,16 @@ export class WebViewContentGenerator {
const disabledCommandsString = isSageMaker() ? `['/dev', '/transform']` : '[]'
const disclaimerAcknowledged = globals.globalState.tryGet('aws.amazonq.disclaimerAcknowledged', Boolean, false)

const welcomeLoadCount = globals.globalState.tryGet('aws.amazonq.welcomeChatShowCount', Number, 0)

return `
<script type="text/javascript" src="${javascriptEntrypoint.toString()}" defer onload="init()"></script>
${cssLinks}
<script type="text/javascript">
const init = () => {
createMynahUI(acquireVsCodeApi(), ${
(await AuthUtil.instance.getChatAuthState()).amazonQ === 'connected'
},${featureConfigsString},${showWelcomePage},${disclaimerAcknowledged},${disabledCommandsString});
},${featureConfigsString},${welcomeLoadCount},${disclaimerAcknowledged},${disabledCommandsString});
}
</script>
`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ export function dispatchWebViewMessagesToApps(
globals.globalState.tryUpdate('aws.amazonq.disclaimerAcknowledged', true)
return
}
case 'update-welcome-count': {
const currentLoadCount = globals.globalState.tryGet('aws.amazonq.welcomeChatShowCount', Number, 0)
void globals.globalState.tryUpdate('aws.amazonq.welcomeChatShowCount', currentLoadCount + 1)
return
}
}

if (msg.type === 'error') {
Expand Down
Loading

0 comments on commit e1c4635

Please sign in to comment.