Skip to content

Commit f2d27ca

Browse files
committed
feat(amazonq): skip registering run command log file
1 parent c3ea31d commit f2d27ca

File tree

4 files changed

+175
-2
lines changed

4 files changed

+175
-2
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "The logs emitted by the Agent during user command execution will be accepted and written to .amazonq/dev/run_command.log file in the user's local repository."
4+
}

packages/core/src/amazonq/session/sessionState.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { prepareRepoData, getDeletedFileInfos, registerNewFiles, PrepareRepoData
2929
import { uploadCode } from '../util/upload'
3030

3131
export const EmptyCodeGenID = 'EMPTY_CURRENT_CODE_GENERATION_ID'
32+
export const RunCommandLogFileName = '.amazonq/dev/run_command.log'
3233

3334
export interface BaseMessenger {
3435
sendAnswer(params: any): void
@@ -103,6 +104,16 @@ export abstract class CodeGenBase {
103104
case CodeGenerationStatus.COMPLETE: {
104105
const { newFileContents, deletedFiles, references } =
105106
await this.config.proxyClient.exportResultArchive(this.conversationId)
107+
108+
const logFileInfo = newFileContents.find(
109+
(file: { zipFilePath: string; fileContent: string }) =>
110+
file.zipFilePath === RunCommandLogFileName
111+
)
112+
if (logFileInfo) {
113+
getLogger().info(`Run Command logs: \n ${logFileInfo.fileContent}`)
114+
newFileContents.splice(newFileContents.indexOf(logFileInfo), 1)
115+
}
116+
106117
const newFileInfo = registerNewFiles(
107118
fs,
108119
newFileContents,

packages/core/src/shared/virtualFilesystem.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ export class VirtualFileSystem implements vscode.FileSystemProvider {
4646
if (this.fileProviders[key] !== undefined) {
4747
throw new Error('Cannot re-register a provider for the same URI')
4848
}
49-
5049
this.fileProviders[key] = provider
5150
const onDidChange = provider.onDidChange(() => {
5251
this._onDidChangeFile.fire([{ uri, type: vscode.FileChangeType.Changed }])

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

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import assert from 'assert'
88
import sinon from 'sinon'
99
import { DocPrepareCodeGenState } from '../../../amazonqDoc'
1010
import { createMockSessionStateAction } from '../../amazonq/utils'
11-
1211
import { createTestContext, setupTestHooks } from '../../amazonq/session/testSetup'
12+
import * as filesModule from '../../../amazonq/util/files'
13+
import { CodeGenBase } from '../../../amazonq/session/sessionState'
14+
import { RunCommandLogFileName } from '../../../amazonq/session/sessionState'
1315

1416
describe('sessionStateDoc', () => {
1517
const context = createTestContext()
@@ -26,4 +28,161 @@ describe('sessionStateDoc', () => {
2628
})
2729
})
2830
})
31+
32+
describe('CodeGenBase generateCode log file handling', () => {
33+
class TestCodeGen extends CodeGenBase {
34+
public generatedFiles: any[] = []
35+
constructor(config: any, tabID: string) {
36+
super(config, tabID)
37+
}
38+
protected handleProgress(_messenger: any): void {
39+
// No-op for test.
40+
}
41+
protected getScheme(): string {
42+
return 'file'
43+
}
44+
protected getTimeoutErrorCode(): string {
45+
return 'test_timeout'
46+
}
47+
protected handleGenerationComplete(_messenger: any, newFileInfo: any[]): void {
48+
this.generatedFiles = newFileInfo
49+
}
50+
protected handleError(_messenger: any, _codegenResult: any): Error {
51+
throw new Error('handleError called')
52+
}
53+
}
54+
55+
let fakeProxyClient: any
56+
let testConfig: any
57+
let fsMock: any
58+
let messengerMock: any
59+
let telemetryMock: any
60+
let loggerMock: any
61+
let testAction: any
62+
let registerNewFilesStub: any
63+
64+
beforeEach(() => {
65+
fakeProxyClient = {
66+
getCodeGeneration: sinon.stub().resolves({
67+
codeGenerationStatus: { status: 'Complete' },
68+
codeGenerationRemainingIterationCount: 0,
69+
codeGenerationTotalIterationCount: 1,
70+
}),
71+
exportResultArchive: sinon.stub(),
72+
}
73+
74+
testConfig = {
75+
conversationId: 'conv_test',
76+
uploadId: 'upload_test',
77+
workspaceRoots: ['/workspace'],
78+
proxyClient: fakeProxyClient,
79+
}
80+
81+
fsMock = {
82+
writeFile: sinon.stub().resolves(),
83+
}
84+
85+
messengerMock = { sendAnswer: sinon.spy() }
86+
87+
telemetryMock = {
88+
setCodeGenerationResult: sinon.spy(),
89+
setNumberOfFilesGenerated: sinon.spy(),
90+
setAmazonqNumberOfReferences: sinon.spy(),
91+
setGenerateCodeIteration: sinon.spy(),
92+
setGenerateCodeLastInvocationTime: sinon.spy(),
93+
recordUserCodeGenerationTelemetry: sinon.spy(),
94+
}
95+
96+
loggerMock = {
97+
addContent: sinon.spy(),
98+
}
99+
100+
testAction = {
101+
fs: fsMock,
102+
messenger: messengerMock,
103+
logger: loggerMock,
104+
tokenSource: { token: { isCancellationRequested: false, onCancellationRequested: () => {} } },
105+
}
106+
107+
registerNewFilesStub = sinon
108+
.stub(filesModule, 'registerNewFiles')
109+
.callsFake((_, newFileContents: any[]) => {
110+
return newFileContents
111+
})
112+
})
113+
114+
afterEach(() => {
115+
sinon.restore()
116+
})
117+
118+
it('adds the log content to logger if present and excludes it from new files', async () => {
119+
const logFileInfo = {
120+
zipFilePath: RunCommandLogFileName,
121+
fileContent: 'newLog',
122+
}
123+
const otherFile = { zipFilePath: 'other.ts', fileContent: 'other content' }
124+
fakeProxyClient.exportResultArchive.resolves({
125+
newFileContents: [logFileInfo, otherFile],
126+
deletedFiles: [],
127+
references: [],
128+
})
129+
130+
const testCodeGen = new TestCodeGen(testConfig, 'tab1')
131+
132+
const result = await testCodeGen.generateCode({
133+
messenger: messengerMock,
134+
fs: fsMock,
135+
codeGenerationId: 'codegen1',
136+
telemetry: telemetryMock,
137+
workspaceFolders: [] as any,
138+
action: testAction,
139+
})
140+
141+
sinon.assert.calledWith(loggerMock.addContent, `Run Command logs: \n ${logFileInfo.fileContent}`)
142+
143+
sinon.assert.calledWith(
144+
registerNewFilesStub,
145+
fsMock,
146+
[otherFile],
147+
testConfig.uploadId,
148+
[] as any,
149+
testConfig.conversationId,
150+
'file'
151+
)
152+
153+
assert.deepStrictEqual(result.newFiles, [otherFile])
154+
})
155+
156+
it('skips log file handling if log file is not present', async () => {
157+
const file1 = { zipFilePath: 'file1.ts', fileContent: 'content1' }
158+
fakeProxyClient.exportResultArchive.resolves({
159+
newFileContents: [file1],
160+
deletedFiles: [],
161+
references: [],
162+
})
163+
164+
const testCodeGen = new TestCodeGen(testConfig, 'tab1')
165+
166+
const result = await testCodeGen.generateCode({
167+
messenger: messengerMock,
168+
fs: fsMock,
169+
codeGenerationId: 'codegen2',
170+
telemetry: telemetryMock,
171+
workspaceFolders: [] as any,
172+
action: testAction,
173+
})
174+
175+
sinon.assert.notCalled(loggerMock.addContent)
176+
sinon.assert.calledWith(
177+
registerNewFilesStub,
178+
fsMock,
179+
[file1],
180+
testConfig.uploadId,
181+
[] as any,
182+
testConfig.conversationId,
183+
'file'
184+
)
185+
assert.deepStrictEqual(result.newFiles, [file1])
186+
})
187+
})
29188
})

0 commit comments

Comments
 (0)