Skip to content

Commit 9393f1f

Browse files
authored
Merge branch 'main' into feature/diff-v2
2 parents 5776383 + fdd89d8 commit 9393f1f

File tree

84 files changed

+564037
-418
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+564037
-418
lines changed

src/ai/CfnAI.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { getFilteredScannedResources, formatScannedResourcesForAI } from '../ser
77
import { SettingsConfigurable, ISettingsSubscriber } from '../settings/ISettingsSubscriber';
88
import { LoggerFactory } from '../telemetry/LoggerFactory';
99
import { Closeable } from '../utils/Closeable';
10-
import { extractErrorMessage } from '../utils/Errors';
1110
import { toString } from '../utils/String';
1211
import { Agent } from './Agent';
1312
import { LLMConfig } from './llm/LLMConfig';
@@ -47,7 +46,7 @@ export class CfnAI implements SettingsConfigurable, Closeable {
4746
try {
4847
return (await this.mcpTools?.getAllTools()) ?? [];
4948
} catch (error) {
50-
logger.warn({ error: extractErrorMessage(error) }, 'Failed to get MCP tools, continuing without tools');
49+
logger.warn(error, 'Failed to get MCP tools, continuing without tools');
5150
return [];
5251
}
5352
}
@@ -129,7 +128,7 @@ export class CfnAI implements SettingsConfigurable, Closeable {
129128
logger.info('No resource scan available');
130129
}
131130
} catch (error) {
132-
logger.warn({ error: extractErrorMessage(error) }, 'Failed to get resource scan data');
131+
logger.warn(error, 'Failed to get resource scan data');
133132
}
134133

135134
return await agent.execute(

src/ai/McpTools.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { SettingsConfigurable, ISettingsSubscriber, SettingsSubscription } from
44
import { DefaultSettings, ProfileSettings } from '../settings/Settings';
55
import { LoggerFactory } from '../telemetry/LoggerFactory';
66
import { Closeable } from '../utils/Closeable';
7-
import { extractErrorMessage } from '../utils/Errors';
87

98
const logger = LoggerFactory.getLogger('McpTools');
109

@@ -57,7 +56,7 @@ export class McpTools implements SettingsConfigurable, Closeable {
5756
await this.mcpClient.initializeConnections();
5857
logger.info('Initialized MCP tools');
5958
} catch (error) {
60-
logger.error({ error: extractErrorMessage(error) }, 'Failed to initialize MCP tools');
59+
logger.error(error, 'Failed to initialize MCP tools');
6160
}
6261
}
6362

@@ -67,7 +66,7 @@ export class McpTools implements SettingsConfigurable, Closeable {
6766

6867
if (this.mcpClient) {
6968
await this.mcpClient.close().catch((error: unknown) => {
70-
logger.error({ error }, 'Failed to close MCP client');
69+
logger.error(error, 'Failed to close MCP client');
7170
});
7271
}
7372
await this.initializeMCP();

src/ai/llm/LLMConfig.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { homedir } from 'os';
33
import { join } from 'path';
44
import { DeepReadonly } from 'ts-essentials';
55
import { LoggerFactory } from '../../telemetry/LoggerFactory';
6-
import { extractErrorMessage } from '../../utils/Errors';
76
import { parseWithPrettyError } from '../../utils/ZodErrorWrapper';
87
import { LLMConfigType, parseLLMConfig } from './LLMTypes';
98

@@ -27,7 +26,7 @@ export class LLMConfig {
2726
logger.info({ provider: llmConfig.provider, model: llmConfig.model }, 'LLM configuration');
2827
return llmConfig;
2928
} catch (error) {
30-
logger.error(`Failed to parse LLM config. ${extractErrorMessage(error)}`);
29+
logger.error(error, `Failed to parse LLM config`);
3130
}
3231
}
3332

src/artifacts/SamResourceDocs.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
export const SAM_RESOURCE_DESCRIPTIONS: ReadonlyMap<string, string> = new Map([
2+
[
3+
'AWS::Serverless::Function',
4+
'Creates a Lambda function, IAM execution role, and event source mappings which trigger the function.',
5+
],
6+
['AWS::Serverless::Api', 'Creates an Amazon API Gateway REST API, which can be managed by Amazon API Gateway.'],
7+
['AWS::Serverless::HttpApi', 'Creates an Amazon API Gateway HTTP API, which can be managed by Amazon API Gateway.'],
8+
['AWS::Serverless::SimpleTable', 'Creates a DynamoDB table with a single attribute primary key.'],
9+
[
10+
'AWS::Serverless::LayerVersion',
11+
'Creates a Lambda LayerVersion that contains library or runtime code needed by a Lambda function.',
12+
],
13+
[
14+
'AWS::Serverless::Application',
15+
'Embeds a serverless application from the AWS Serverless Application Repository or from an Amazon S3 bucket.',
16+
],
17+
[
18+
'AWS::Serverless::StateMachine',
19+
'Creates an AWS Step Functions state machine, which can be managed by Step Functions.',
20+
],
21+
['AWS::Serverless::Connector', 'Manages permissions between AWS resources.'],
22+
['AWS::Serverless::GraphQLApi', 'Creates an AWS AppSync GraphQL API.'],
23+
]);
24+
25+
export const SAM_DOCUMENTATION_URLS: ReadonlyMap<string, string> = new Map([
26+
[
27+
'AWS::Serverless::Function',
28+
'https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html',
29+
],
30+
[
31+
'AWS::Serverless::Api',
32+
'https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-api.html',
33+
],
34+
[
35+
'AWS::Serverless::HttpApi',
36+
'https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-httpapi.html',
37+
],
38+
[
39+
'AWS::Serverless::SimpleTable',
40+
'https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-simpletable.html',
41+
],
42+
[
43+
'AWS::Serverless::LayerVersion',
44+
'https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-layerversion.html',
45+
],
46+
[
47+
'AWS::Serverless::Application',
48+
'https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-application.html',
49+
],
50+
[
51+
'AWS::Serverless::StateMachine',
52+
'https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-statemachine.html',
53+
],
54+
[
55+
'AWS::Serverless::Connector',
56+
'https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-connector.html',
57+
],
58+
[
59+
'AWS::Serverless::GraphQLApi',
60+
'https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-graphqlapi.html',
61+
],
62+
]);

src/auth/AwsCredentials.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { LspAuthHandlers } from '../protocol/LspAuthHandlers';
55
import { DefaultSettings } from '../settings/Settings';
66
import { SettingsManager } from '../settings/SettingsManager';
77
import { LoggerFactory } from '../telemetry/LoggerFactory';
8-
import { extractErrorMessage } from '../utils/Errors';
98
import { getRegion } from '../utils/Region';
109
import { parseWithPrettyError } from '../utils/ZodErrorWrapper';
1110
import { UpdateCredentialsParams, IamCredentials } from './AwsLspAuthTypes';
@@ -24,14 +23,14 @@ export class AwsCredentials {
2423
private readonly logger = LoggerFactory.getLogger(AwsCredentials);
2524

2625
private iamCredentials?: IamCredentials;
27-
private readonly encryptionKey: Buffer;
26+
private readonly encryptionKey?: Buffer;
2827

2928
constructor(
3029
private readonly awsHandlers: LspAuthHandlers,
3130
private readonly settingsManager: SettingsManager,
32-
encryptionKey: string,
31+
encryptionKey?: string,
3332
) {
34-
this.encryptionKey = Buffer.from(encryptionKey, 'base64');
33+
this.encryptionKey = encryptionKey ? Buffer.from(encryptionKey, 'base64') : undefined;
3534
}
3635

3736
getIAM(): DeepReadonly<IamCredentials> {
@@ -42,6 +41,11 @@ export class AwsCredentials {
4241
}
4342

4443
async handleIamCredentialsUpdate(params: UpdateCredentialsParams): Promise<boolean> {
44+
if (!this.encryptionKey) {
45+
this.logger.error('Authentication failed: encryption key not configured');
46+
return false;
47+
}
48+
4549
try {
4650
const decrypted = await compactDecrypt(params.data, this.encryptionKey);
4751
const rawCredentials = JSON.parse(new TextDecoder().decode(decrypted.plaintext)) as unknown;
@@ -63,7 +67,7 @@ export class AwsCredentials {
6367
} catch (error) {
6468
this.iamCredentials = undefined;
6569

66-
this.logger.error(`Failed to update IAM credentials: ${extractErrorMessage(error)}`);
70+
this.logger.error(error, `Failed to update IAM credentials`);
6771
this.settingsManager.updateProfileSettings(DefaultSettings.profile.profile, DefaultSettings.profile.region);
6872
return false;
6973
}

src/autocomplete/CompletionFormatter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class CompletionFormatter {
4949
items: formattedItems,
5050
};
5151
} catch (error) {
52-
CompletionFormatter.log.warn({ error }, 'Failed to adapt completions');
52+
CompletionFormatter.log.warn(error, 'Failed to adapt completions');
5353
return completions;
5454
}
5555
}

src/autocomplete/ConditionCompletionProvider.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,6 @@ export class ConditionCompletionProvider implements CompletionProvider {
2222
public constructor(private readonly syntaxTreeManager: SyntaxTreeManager) {}
2323

2424
public getCompletions(context: Context, params: CompletionParams): CompletionItem[] | undefined {
25-
this.log.debug(
26-
{
27-
provider: 'Condition Completion',
28-
position: params.position,
29-
},
30-
'Processing condition completion request',
31-
);
32-
3325
const syntaxTree = this.syntaxTreeManager.getSyntaxTree(params.textDocument.uri);
3426
if (!syntaxTree) {
3527
return;

src/autocomplete/IntrinsicFunctionArgumentCompletionProvider.ts

Lines changed: 6 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,6 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
7171
return undefined;
7272
}
7373

74-
log.debug(
75-
{
76-
provider: 'IntrinsicFunctionArgument',
77-
context: context.record(),
78-
intrinsicFunction: intrinsicFunction.type,
79-
args: intrinsicFunction.args,
80-
},
81-
'Processing intrinsic function argument completion request',
82-
);
83-
8474
// Route to specific handlers based on intrinsic function type
8575
switch (intrinsicFunction.type) {
8676
case IntrinsicFunction.Ref: {
@@ -106,14 +96,6 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
10696
params: CompletionParams,
10797
syntaxTree: SyntaxTree,
10898
): CompletionItem[] | undefined {
109-
log.debug(
110-
{
111-
provider: 'IntrinsicFunctionArgument',
112-
function: 'Ref',
113-
context: context.record(),
114-
},
115-
'Processing Ref argument completion',
116-
);
11799
const parametersAndResourcesCompletions = this.getParametersAndResourcesAsCompletionItems(
118100
context,
119101
params,
@@ -135,14 +117,6 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
135117
params: CompletionParams,
136118
syntaxTree: SyntaxTree,
137119
): CompletionItem[] | undefined {
138-
log.debug(
139-
{
140-
provider: 'IntrinsicFunctionArgument',
141-
function: 'Sub',
142-
context: context.record(),
143-
},
144-
'Processing Sub argument completion',
145-
);
146120
const parametersAndResourcesCompletions = this.getParametersAndResourcesAsCompletionItems(
147121
context,
148122
params,
@@ -193,34 +167,26 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
193167
syntaxTree: SyntaxTree,
194168
intrinsicFunction: IntrinsicFunctionInfo,
195169
): CompletionItem[] | undefined {
196-
log.debug(
197-
{ provider: 'FindInMap Completion', context: context.record() },
198-
'Processing FindInMap completion request',
199-
);
200-
201170
// Validate that mappings exist in the template
202171
const mappingsMap = getEntityMap(syntaxTree, TopLevelSection.Mappings);
203172
if (!mappingsMap || mappingsMap.size === 0) {
204-
log.debug('No mappings found in template for FindInMap completion');
205173
return undefined;
206174
}
207175

208176
try {
209177
// Determine position in FindInMap arguments
210178
const position = this.determineFindInMapPosition(intrinsicFunction.args, context);
211-
log.debug(`FindInMap argument position determined: ${position}`);
212179

213180
// Get completions based on position
214181
const completions = this.getCompletionsByPosition(position, mappingsMap, intrinsicFunction.args, context);
215182

216183
if (!completions) {
217-
log.debug(`No completions found for FindInMap position ${position}`);
218184
return undefined;
219185
}
220186

221187
return completions;
222188
} catch (error) {
223-
log.error({ error }, 'Error processing FindInMap completions');
189+
log.error(error, 'Error processing FindInMap completions');
224190
return undefined;
225191
}
226192
}
@@ -362,7 +328,7 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
362328
attributeDescription = resolvedSchemas[0].description;
363329
}
364330
} catch (error) {
365-
log.error({ error }, 'Error resolving JSON Pointer path');
331+
log.error(error, 'Error resolving JSON pointer path');
366332
}
367333
}
368334
completionItems.push(
@@ -461,7 +427,6 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
461427
): CompletionItem[] | undefined {
462428
// Validate position is within expected range for FindInMap (1-3)
463429
if (position < 1 || position > 3) {
464-
log.debug(`Invalid FindInMap position: ${position}`);
465430
return undefined;
466431
}
467432

@@ -489,7 +454,7 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
489454

490455
return context.text.length > 0 ? this.fuzzySearch(items, context.text) : items;
491456
} catch (error) {
492-
log.error({ error }, 'Error creating mapping name completions');
457+
log.error(error, 'Error creating mapping name completions');
493458
return [];
494459
}
495460
}
@@ -501,21 +466,18 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
501466
): CompletionItem[] | undefined {
502467
// Validate arguments structure
503468
if (!Array.isArray(args) || args.length === 0 || typeof args[0] !== 'string') {
504-
log.debug('Invalid arguments for top-level key completions');
505469
return undefined;
506470
}
507471

508472
try {
509473
const mappingName = args[0];
510474
const mappingEntity = this.getMappingEntity(mappingsEntities, mappingName);
511475
if (!mappingEntity) {
512-
log.debug(`Mapping entity not found: ${mappingName}`);
513476
return undefined;
514477
}
515478

516479
const topLevelKeys = mappingEntity.getTopLevelKeys();
517480
if (topLevelKeys.length === 0) {
518-
log.debug(`No top-level keys found for mapping: ${mappingName}`);
519481
return undefined;
520482
}
521483

@@ -525,7 +487,7 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
525487

526488
return context.text.length > 0 ? this.fuzzySearch(items, context.text) : items;
527489
} catch (error) {
528-
log.error({ error }, 'Error creating top-level key completions');
490+
log.error(error, 'Error creating top-level key completions');
529491
return undefined;
530492
}
531493
}
@@ -537,7 +499,6 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
537499
): CompletionItem[] | undefined {
538500
// Validate arguments structure for second-level keys
539501
if (!this.isValidSecondLevelKeyArgs(args)) {
540-
log.debug('Invalid arguments for second-level key completions');
541502
return undefined;
542503
}
543504

@@ -547,13 +508,11 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
547508

548509
const mappingEntity = this.getMappingEntity(mappingsEntities, mappingName);
549510
if (!mappingEntity) {
550-
log.debug(`Mapping entity not found: ${mappingName}`);
551511
return undefined;
552512
}
553513

554514
const secondLevelKeys = this.getSecondLevelKeysForTopLevelKey(mappingEntity, topLevelKey);
555515
if (secondLevelKeys.length === 0) {
556-
log.debug(`No second-level keys found for mapping: ${mappingName}`);
557516
return undefined;
558517
}
559518

@@ -563,7 +522,7 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
563522

564523
return this.filterSecondLevelKeyItems(items, context, topLevelKey);
565524
} catch (error) {
566-
log.debug({ error }, 'Error creating second-level key completions');
525+
log.warn(error, 'Error creating second-level key completions');
567526
return undefined;
568527
}
569528
}
@@ -647,7 +606,7 @@ export class IntrinsicFunctionArgumentCompletionProvider implements CompletionPr
647606
}
648607
return mappingContext.entity as Mapping;
649608
} catch (error) {
650-
log.error({ error }, `Error retrieving mapping entity: ${mappingName}`);
609+
log.error(error, `Error retrieving mapping entity: ${mappingName}`);
651610
return undefined;
652611
}
653612
}

0 commit comments

Comments
 (0)