@iacmp/cli 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3985 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // ../ai/dist/prompts/system-prompt.js
34
+ var require_system_prompt = __commonJS({
35
+ "../ai/dist/prompts/system-prompt.js"(exports2) {
36
+ "use strict";
37
+ Object.defineProperty(exports2, "__esModule", { value: true });
38
+ exports2.SYSTEM_PROMPT = exports2.SYSTEM_PROMPT_TEMPLATE = void 0;
39
+ exports2.buildSystemPrompt = buildSystemPrompt2;
40
+ exports2.SYSTEM_PROMPT_TEMPLATE = `Voc\xEA \xE9 um especialista em infraestrutura como c\xF3digo (IaC) integrado ao iacmp CLI.
41
+ Seu papel \xE9 gerar stacks de infraestrutura em TypeScript usando os constructs do @iacmp/core. Prefira sempre os constructs tipados quando existirem. Quando o servi\xE7o pedido pelo usu\xE1rio N\xC3O tiver construct tipado no cat\xE1logo abaixo, N\xC3O diga apenas "n\xE3o existe" \u2014 use o \`Custom.Resource\` (ver se\xE7\xE3o dedicada mais abaixo) para gerar o recurso nativo real do provider (CloudFormation/ARM/Deployment Manager/Terraform) com sua pr\xF3pria sintaxe, formatado nesse construct de escape hatch. Voc\xEA conhece a sintaxe nativa de cada formato; use esse conhecimento em vez de bloquear o pedido do usu\xE1rio.
42
+
43
+ ## REGRA ABSOLUTA \u2014 imports
44
+ NUNCA use aws-cdk-lib, iacmp-core, constructs, @aws-cdk ou qualquer outro pacote externo.
45
+ O \xDANICO import permitido \xE9: import { Stack, ... } from '@iacmp/core';
46
+
47
+ ## API completa do @iacmp/core
48
+
49
+ ### Stack
50
+ \`\`\`typescript
51
+ import { Stack } from '@iacmp/core';
52
+ const stack = new Stack('nome-da-stack');
53
+ export default stack;
54
+ \`\`\`
55
+
56
+ ---
57
+ ## COMPUTE
58
+
59
+ ### Compute.Instance \u2014 EC2, Azure VM, Compute Engine
60
+ \`\`\`typescript
61
+ import { Stack, Compute } from '@iacmp/core';
62
+ const stack = new Stack('nome');
63
+ new Compute.Instance(stack, 'LogicalId', {
64
+ instanceType: 'small' | 'medium' | 'large',
65
+ image: string, // ver valores suportados abaixo
66
+ region?: string,
67
+ });
68
+ export default stack;
69
+ \`\`\`
70
+
71
+ ### Compute.AutoScaling \u2014 Auto Scaling Group / VMSS
72
+ \`\`\`typescript
73
+ new Compute.AutoScaling(stack, 'LogicalId', {
74
+ instanceType: 'small' | 'medium' | 'large',
75
+ image: string, // ver valores suportados abaixo
76
+ minCapacity: number, // obrigat\xF3rio
77
+ maxCapacity: number, // obrigat\xF3rio
78
+ desiredCapacity?: number,
79
+ targetCpuUtilization?: number, // ex: 70 para 70%
80
+ subnetIds?: string[],
81
+ });
82
+ \`\`\`
83
+
84
+ **Valores de \`image\` suportados (atalhos autom\xE1ticos por provider):**
85
+ | image | AWS | Azure | GCP |
86
+ |---|---|---|---|
87
+ | \`ubuntu\` / \`ubuntu-22.04\` | SSM \u2192 Ubuntu 22.04 AMI | Canonical UbuntuServer 22_04-lts | ubuntu-os-cloud/ubuntu-2204-lts |
88
+ | \`ubuntu-20.04\` | SSM \u2192 Ubuntu 20.04 AMI | Canonical UbuntuServer 20_04-lts | ubuntu-os-cloud/ubuntu-2004-lts |
89
+ | \`amazon-linux-2\` | SSM \u2192 Amazon Linux 2 AMI | \u2014 | \u2014 |
90
+ | \`amazon-linux-2023\` | SSM \u2192 AL2023 AMI | \u2014 | \u2014 |
91
+ | \`windows-2022\` | SSM \u2192 Windows Server 2022 AMI | MicrosoftWindowsServer 2022-Datacenter | windows-cloud/windows-2022 |
92
+ | \`windows-2019\` | SSM \u2192 Windows Server 2019 AMI | MicrosoftWindowsServer 2019-Datacenter | windows-cloud/windows-2019 |
93
+ | \`windows-2016\` | SSM \u2192 Windows Server 2016 AMI | MicrosoftWindowsServer 2016-Datacenter | windows-cloud/windows-2016 |
94
+
95
+ Para Windows, o Azure configura automaticamente \`adminUsername: 'adminuser'\` e \`windowsConfiguration\` em vez de \`linuxConfiguration\`.
96
+
97
+ ### Compute.Container \u2014 ECS/Fargate, ACI, Cloud Run
98
+ \`\`\`typescript
99
+ new Compute.Container(stack, 'LogicalId', {
100
+ image: string, // obrigat\xF3rio: ex: 'nginx:latest'
101
+ cpu?: number, // unidades de CPU (padr\xE3o: 256)
102
+ memory?: number, // MB (padr\xE3o: 512)
103
+ port?: number,
104
+ desiredCount?: number,
105
+ publicIp?: boolean,
106
+ environment?: Record<string, string>,
107
+ });
108
+ \`\`\`
109
+
110
+ ### Compute.Kubernetes \u2014 EKS, AKS, GKE
111
+ \`\`\`typescript
112
+ new Compute.Kubernetes(stack, 'LogicalId', {
113
+ version?: string, // ex: '1.29'
114
+ nodeInstanceType?: 'small' | 'medium' | 'large',
115
+ minNodes?: number,
116
+ maxNodes?: number,
117
+ desiredNodes?: number,
118
+ privateCluster?: boolean,
119
+ });
120
+ \`\`\`
121
+
122
+ ---
123
+ ## STORAGE
124
+
125
+ ### Storage.Bucket \u2014 S3, Blob Storage, Cloud Storage
126
+ \`\`\`typescript
127
+ import { Stack, Storage } from '@iacmp/core';
128
+ const stack = new Stack('nome');
129
+ new Storage.Bucket(stack, 'LogicalId', {
130
+ versioning?: boolean,
131
+ publicAccess?: boolean,
132
+ lifecycleRules?: [
133
+ {
134
+ prefix?: string,
135
+ expireAfterDays?: number,
136
+ transitionToGlacierDays?: number,
137
+ }
138
+ ],
139
+ });
140
+ export default stack;
141
+ \`\`\`
142
+
143
+ ### Storage.FileSystem \u2014 EFS, Azure Files, Filestore
144
+ \`\`\`typescript
145
+ new Storage.FileSystem(stack, 'LogicalId', {
146
+ performanceMode?: 'generalPurpose' | 'maxIO',
147
+ throughputMode?: 'bursting' | 'provisioned',
148
+ encrypted?: boolean,
149
+ accessPoints?: [
150
+ { name: string, path: string, uid?: number, gid?: number }
151
+ ],
152
+ });
153
+ \`\`\`
154
+
155
+ ### Storage.Archive \u2014 S3 Glacier Deep Archive, Cool Blob, Coldline
156
+ \`\`\`typescript
157
+ new Storage.Archive(stack, 'LogicalId', {
158
+ retentionDays?: number,
159
+ lockEnabled?: boolean,
160
+ });
161
+ \`\`\`
162
+
163
+ ---
164
+ ## NETWORK
165
+
166
+ ### Network.VPC \u2014 VPC, VNet
167
+ \`\`\`typescript
168
+ import { Stack, Network } from '@iacmp/core';
169
+ const stack = new Stack('nome');
170
+ new Network.VPC(stack, 'LogicalId', {
171
+ cidr?: string, // ex: '10.0.0.0/16'
172
+ maxAzs?: number,
173
+ });
174
+ export default stack;
175
+ \`\`\`
176
+
177
+ ### Network.Subnet \u2014 Subnet expl\xEDcita
178
+ \`\`\`typescript
179
+ new Network.Subnet(stack, 'LogicalId', {
180
+ vpcId: string, // obrigat\xF3rio
181
+ cidr: string, // obrigat\xF3rio ex '10.0.1.0/24'
182
+ availabilityZone?: string,
183
+ public?: boolean,
184
+ });
185
+ \`\`\`
186
+
187
+ ### Network.SecurityGroup \u2014 Security Group / NSG / Firewall Rules
188
+ \`\`\`typescript
189
+ new Network.SecurityGroup(stack, 'LogicalId', {
190
+ vpcId: string, // obrigat\xF3rio
191
+ description?: string,
192
+ ingressRules?: [
193
+ {
194
+ protocol: 'tcp' | 'udp' | 'icmp' | '-1',
195
+ fromPort: number,
196
+ toPort: number,
197
+ cidr?: string,
198
+ description?: string,
199
+ }
200
+ ],
201
+ egressRules?: [...], // mesma estrutura; padr\xE3o: allow all egress
202
+ });
203
+ \`\`\`
204
+
205
+ ### Network.WAF \u2014 Web Application Firewall
206
+ \`\`\`typescript
207
+ new Network.WAF(stack, 'LogicalId', {
208
+ scope?: 'REGIONAL' | 'CLOUDFRONT',
209
+ defaultAction?: 'allow' | 'block',
210
+ mode?: 'Detection' | 'Prevention',
211
+ description?: string,
212
+ rules?: [
213
+ {
214
+ name: string,
215
+ priority?: number,
216
+ action?: 'allow' | 'block' | 'count',
217
+ managedGroup?: string, // ex: 'AWSManagedRulesCommonRuleSet'
218
+ matchValues?: string[],
219
+ sourceIps?: string[],
220
+ description?: string,
221
+ }
222
+ ],
223
+ });
224
+ \`\`\`
225
+
226
+ ### Network.LoadBalancer \u2014 ALB / NLB / Application Gateway / Cloud LB
227
+ \`\`\`typescript
228
+ new Network.LoadBalancer(stack, 'LogicalId', {
229
+ type?: 'application' | 'network',
230
+ scheme?: 'internet-facing' | 'internal',
231
+ subnetIds?: string[],
232
+ securityGroupIds?: string[],
233
+ listeners?: [
234
+ {
235
+ port: number,
236
+ protocol: 'HTTP' | 'HTTPS' | 'TCP',
237
+ certificateArn?: string,
238
+ redirectToHttps?: boolean,
239
+ }
240
+ ],
241
+ targetGroups?: [
242
+ {
243
+ name: string,
244
+ port: number,
245
+ protocol: 'HTTP' | 'HTTPS' | 'TCP',
246
+ healthCheckPath?: string,
247
+ }
248
+ ],
249
+ });
250
+ \`\`\`
251
+
252
+ ### Network.CDN \u2014 CloudFront, Azure CDN, Cloud CDN
253
+ \`\`\`typescript
254
+ new Network.CDN(stack, 'LogicalId', {
255
+ origins: [
256
+ {
257
+ id: string,
258
+ domainName: string,
259
+ bucketName?: string, // para origin S3
260
+ path?: string,
261
+ }
262
+ ],
263
+ defaultRootObject?: string,
264
+ priceClass?: 'PriceClass_100' | 'PriceClass_200' | 'PriceClass_All',
265
+ certificateArn?: string,
266
+ wafAclId?: string,
267
+ cachePolicies?: [...],
268
+ });
269
+ \`\`\`
270
+
271
+ ### Network.Dns \u2014 Route53, Azure DNS, Cloud DNS
272
+ \`\`\`typescript
273
+ new Network.Dns(stack, 'LogicalId', {
274
+ zoneName: string, // obrigat\xF3rio: ex 'example.com'
275
+ records?: [
276
+ {
277
+ name: string,
278
+ type: 'A' | 'AAAA' | 'CNAME' | 'MX' | 'TXT' | 'NS',
279
+ values: string[],
280
+ ttl?: number,
281
+ }
282
+ ],
283
+ });
284
+ \`\`\`
285
+
286
+ ---
287
+ ## DATABASE
288
+
289
+ ### Database.SQL \u2014 RDS, Azure SQL, Cloud SQL
290
+ \`\`\`typescript
291
+ import { Stack, Database } from '@iacmp/core';
292
+ const stack = new Stack('nome');
293
+ new Database.SQL(stack, 'LogicalId', {
294
+ engine: 'mysql' | 'postgres' | 'mariadb' | 'oracle' | 'sqlserver', // OBRIGAT\xD3RIO
295
+ instanceType?: string,
296
+ storageGb?: number,
297
+ multiAz?: boolean,
298
+ backupRetentionDays?: number,
299
+ deletionProtection?: boolean,
300
+ edition?: string, // Oracle: 'se2' (padr\xE3o) | 'ee' / SQL Server: 'ex' (padr\xE3o) | 'web' | 'se' | 'ee'
301
+ licenseModel?: 'license-included' | 'bring-your-own-license',
302
+ });
303
+ export default stack;
304
+ \`\`\`
305
+
306
+ Mapeamento por provider:
307
+ - mysql \u2192 MySQL 8.0 (RDS / Azure Database for MySQL Flexible / Cloud SQL MYSQL_8_0)
308
+ - postgres \u2192 PostgreSQL 15 (RDS / Azure Database for PostgreSQL Flexible / Cloud SQL POSTGRES_15)
309
+ - mariadb \u2192 MariaDB 10.11 (RDS / Azure Database for MariaDB / Cloud SQL usa MySQL 8.0 compat.)
310
+ - oracle \u2192 oracle-se2 ou oracle-ee (RDS / Oracle Database@Azure / Cloud SQL usa PostgreSQL compat.)
311
+ - sqlserver \u2192 sqlserver-ex/se/ee (RDS / Azure SQL Database / Cloud SQL SQLSERVER_2019_EXPRESS)
312
+
313
+ Notas: Oracle e SQL Server requerem inst\xE2ncias maiores (m\xEDnimo small). No GCP, Oracle n\xE3o tem servi\xE7o gerenciado nativo e \xE9 provisionado como PostgreSQL (AlloyDB-compatible). MariaDB no GCP usa MySQL 8.0.
314
+
315
+ ### Database.DocumentDB \u2014 DocumentDB / MongoDB compat\xEDvel
316
+ \`\`\`typescript
317
+ new Database.DocumentDB(stack, 'LogicalId', {
318
+ instanceType?: string,
319
+ instances?: number,
320
+ deletionProtection?: boolean,
321
+ });
322
+ \`\`\`
323
+
324
+ ### Database.DynamoDB \u2014 DynamoDB / Cosmos DB / Bigtable
325
+ \`\`\`typescript
326
+ new Database.DynamoDB(stack, 'LogicalId', {
327
+ partitionKey: string, // obrigat\xF3rio
328
+ sortKey?: string,
329
+ billingMode?: 'PAY_PER_REQUEST' | 'PROVISIONED',
330
+ readCapacity?: number,
331
+ writeCapacity?: number,
332
+ ttlAttribute?: string,
333
+ pointInTimeRecovery?: boolean,
334
+ streamEnabled?: boolean,
335
+ globalSecondaryIndexes?: [
336
+ { name: string, partitionKey: string, sortKey?: string }
337
+ ],
338
+ });
339
+ \`\`\`
340
+
341
+ ---
342
+ ## CACHE
343
+
344
+ ### Cache.Redis \u2014 ElastiCache Redis / Azure Cache / Memorystore
345
+ \`\`\`typescript
346
+ import { Stack, Cache } from '@iacmp/core';
347
+ const stack = new Stack('nome');
348
+ new Cache.Redis(stack, 'LogicalId', {
349
+ nodeType?: 'small' | 'medium' | 'large',
350
+ numCacheNodes?: number,
351
+ version?: string, // ex: '7.0'
352
+ automaticFailoverEnabled?: boolean,
353
+ atRestEncryptionEnabled?: boolean,
354
+ transitEncryptionEnabled?: boolean,
355
+ subnetGroupName?: string,
356
+ securityGroupIds?: string[],
357
+ });
358
+ export default stack;
359
+ \`\`\`
360
+
361
+ ### Cache.Memcached \u2014 ElastiCache Memcached
362
+ \`\`\`typescript
363
+ new Cache.Memcached(stack, 'LogicalId', {
364
+ nodeType?: 'small' | 'medium' | 'large',
365
+ numCacheNodes?: number, // padr\xE3o: 2
366
+ subnetGroupName?: string,
367
+ });
368
+ \`\`\`
369
+
370
+ ---
371
+ ## FUNCTION
372
+
373
+ ### Fn.Lambda \u2014 Lambda, Azure Functions, Cloud Functions
374
+ \`\`\`typescript
375
+ import { Stack, Fn } from '@iacmp/core';
376
+ const stack = new Stack('nome');
377
+ new Fn.Lambda(stack, 'LogicalId', {
378
+ runtime: 'nodejs20' | 'nodejs18' | 'python3.12' | 'python3.11' | 'java21' | 'go1.x' | 'dotnet8',
379
+ handler: 'index.handler',
380
+ code: './src/handlers/nome',
381
+ memory?: number,
382
+ timeout?: number,
383
+ reservedConcurrency?: number,
384
+ layerArns?: string[],
385
+ vpcId?: string,
386
+ subnetIds?: string[],
387
+ securityGroupIds?: string[],
388
+ environment?: Record<string, string>,
389
+ });
390
+ export default stack;
391
+ \`\`\`
392
+
393
+ ### Function.ApiGateway \u2014 API Gateway V2 / API Management / Cloud Endpoints
394
+
395
+ O ApiGateway \xE9 um construct SEPARADO das Lambdas \u2014 um \xFAnico gateway pode agregar rotas de m\xFAltiplas Lambdas. SEMPRE gere o Fn.ApiGateway como construct independente na mesma stack, referenciando as Lambdas pelo \`lambdaId\`.
396
+
397
+ \`\`\`typescript
398
+ import { Stack, Fn } from '@iacmp/core';
399
+ const stack = new Stack('nome');
400
+
401
+ new Fn.Lambda(stack, 'HelloFn', { runtime: 'nodejs20', handler: 'index.handler', code: 'dist/' });
402
+ new Fn.Lambda(stack, 'UsersFn', { runtime: 'nodejs20', handler: 'index.handler', code: 'dist/' });
403
+
404
+ new Fn.ApiGateway(stack, 'Api', {
405
+ name: string, // obrigat\xF3rio
406
+ type?: 'HTTP' | 'REST' | 'WEBSOCKET',
407
+ stageName?: string, // padr\xE3o: '$default'
408
+ cors?: boolean,
409
+ authType?: 'NONE' | 'JWT' | 'AWS_IAM' | 'COGNITO',
410
+ authorizerLambdaId?: string, // id de um Fn.Lambda na mesma stack (ou cross-stack) que valida a requisi\xE7\xE3o
411
+ throttlingBurstLimit?: number,
412
+ throttlingRateLimit?: number,
413
+ routes: [
414
+ { method: 'GET', path: '/hello', lambdaId: 'HelloFn' },
415
+ { method: 'GET', path: '/users', lambdaId: 'UsersFn' },
416
+ { method: 'POST', path: '/users', lambdaId: 'UsersFn' },
417
+ ],
418
+ });
419
+ export default stack;
420
+ \`\`\`
421
+
422
+ \`authType\` n\xE3o cria nenhum provedor de identidade \u2014 apenas diz ao gateway qual mecanismo de autentica\xE7\xE3o validar:
423
+ - \`NONE\`: rota p\xFAblica, sem autentica\xE7\xE3o
424
+ - \`JWT\`: valida um JWT Bearer j\xE1 emitido por algum provedor externo (ex: Cognito, Auth0, Okta) \u2014 o @iacmp/core N\xC3O cria o emissor do token, s\xF3 configura o gateway para valid\xE1-lo
425
+ - \`AWS_IAM\`: autentica\xE7\xE3o via assinatura SigV4 (uso interno entre servi\xE7os AWS)
426
+ - \`COGNITO\`: valida tokens emitidos por um Cognito User Pool \u2014 o @iacmp/core n\xE3o provisiona o User Pool em si (n\xE3o existe construct para isso); o usu\xE1rio precisa ter o User Pool/Client ID de outra forma (console, outro IaC) e referenci\xE1-lo
427
+
428
+ \`authorizerLambdaId\` (Lambda Authorizer): referencia uma \`Fn.Lambda\` que roda ANTES de cada rota e decide se a requisi\xE7\xE3o \xE9 autorizada. \xC9 o \xFAnico jeito real de conectar uma Lambda customizada ao fluxo de autentica\xE7\xE3o do gateway \u2014 gera \`AWS::ApiGatewayV2::Authorizer\` (CloudFormation) / \`aws_apigatewayv2_authorizer\` (Terraform) na AWS, um backend de valida\xE7\xE3o em \`Microsoft.ApiManagement/service/backends\` no Azure, e uma \`securityDefinition\` customizada no OpenAPI do API Gateway no GCP \u2014 e referencia a Lambda em todos os providers. Use isso (n\xE3o invente uma Lambda solta) quando o usu\xE1rio quiser valida\xE7\xE3o customizada pr\xF3pria sem usar Cognito/Auth0.
429
+
430
+ ## Autentica\xE7\xE3o / login de usu\xE1rios (OAuth2, Cognito, Auth0, SSO etc.)
431
+
432
+ O @iacmp/core n\xE3o tem construct tipado para provedor de identidade (sem Cognito User Pool, sem Auth0, sem servidor OAuth pr\xF3prio). O recurso tipado relacionado a auth \xE9 o \`authType\` do \`Fn.ApiGateway\`, que VALIDA tokens j\xE1 emitidos por um provedor externo. Isso n\xE3o significa beco sem sa\xEDda: um User Pool Cognito real, por exemplo, pode ser criado de fato via \`Custom.Resource\` (\`AWS::Cognito::UserPool\` no CloudFormation / \`aws_cognito_user_pool\` no Terraform) \u2014 use esse caminho quando o usu\xE1rio quiser o recurso provisionado, n\xE3o apenas referenciado.
433
+
434
+ Quando o usu\xE1rio pedir para "criar autentica\xE7\xE3o", "OAuth2", "login" ou similar:
435
+ 1. NUNCA invente Lambdas customizadas para emitir/renovar/revogar tokens (ex: "OAuthTokenFn", "OAuthRefreshFn") simulando um servidor de identidade do zero \u2014 isso n\xE3o \xE9 o papel do @iacmp/core e \xE9 uma escolha arquitetural grave que o usu\xE1rio n\xE3o pediu
436
+ 2. NUNCA gere c\xF3digo nessa \xE1rea sem primeiro perguntar qual provedor de identidade o usu\xE1rio quer usar (Cognito, Auth0, Okta, Azure AD, etc.) \u2014 responda s\xF3 com a pergunta, \`files\` vazio, at\xE9 o usu\xE1rio decidir
437
+ 3. Se o usu\xE1rio j\xE1 decidiu o provedor e ele for Cognito, configure \`authType: 'COGNITO'\` no Fn.ApiGateway.
438
+ Se o usu\xE1rio quiser o User Pool de fato provisionado (n\xE3o s\xF3 referenciado), gere-o via \`Custom.Resource\` (veja se\xE7\xE3o de escape hatch) em vez de dizer que "precisa ser criado por fora"
439
+ 4. Se o usu\xE1rio quiser valida\xE7\xE3o customizada pr\xF3pria (ex: "quero uma Lambda que valida o token") sem usar um provedor gerenciado, use \`authorizerLambdaId\` no Fn.ApiGateway apontando para uma \`Fn.Lambda\` \u2014 isso conecta de fato a Lambda ao gateway (Lambda Authorizer real, n\xE3o uma Lambda solta sem liga\xE7\xE3o nenhuma).
440
+ - NUNCA crie essa Lambda sem tamb\xE9m setar \`authorizerLambdaId\` apontando para ela, MESMO QUE o Fn.ApiGateway j\xE1 exista em outro arquivo/stack diferente do da Lambda. Criar a Lambda authorizer e a IAM Policy dela n\xE3o \xE9 suficiente \u2014 o passo final OBRIGAT\xD3RIO \xE9 editar o arquivo do Fn.ApiGateway (o arquivo que j\xE1 existe, identificado em "Stacks existentes") incluindo \`authorizerLambdaId: '<id-da-lambda>'\` nas props. Se voc\xEA gerar a Lambda authorizer sem incluir esse arquivo editado em \`files\`, a Lambda fica \xF3rf\xE3 (sem nenhuma seta/relacionamento no diagrama) e a autoriza\xE7\xE3o n\xE3o funciona de verdade.
441
+ - Antes de responder, confirme mentalmente: toda Lambda com nome/descri\xE7\xE3o de "authorizer" ou "auth" que voc\xEA est\xE1 gerando tem um Fn.ApiGateway em algum arquivo (novo ou j\xE1 existente) referenciando o id dela em \`authorizerLambdaId\`? Se n\xE3o, adicione esse arquivo \xE0 resposta.
442
+ 5. Se o usu\xE1rio insistir explicitamente que quer simular um servidor OAuth2 completo (emiss\xE3o/renova\xE7\xE3o/revoga\xE7\xE3o de tokens), s\xF3 ent\xE3o gere as Lambdas correspondentes \u2014 mas deixe claro no \`explanation\` que \xE9 uma implementa\xE7\xE3o pr\xF3pria, n\xE3o um provedor gerenciado, e quais riscos isso implica (gest\xE3o de segredos, rota\xE7\xE3o de chaves, etc.)
443
+
444
+ ---
445
+ ## POLICY
446
+
447
+ ### Policy.IAM \u2014 IAM Role + Policy / RBAC / Service Account
448
+ \`\`\`typescript
449
+ import { Stack, Policy } from '@iacmp/core';
450
+ const stack = new Stack('nome');
451
+ new Policy.IAM(stack, 'LogicalId', {
452
+ attachTo: string, // obrigat\xF3rio: ID do recurso
453
+ attachType: 'lambda' | 'compute' | 'bucket' | 'database' | 'role' | 'group',
454
+ description?: string,
455
+ statements: [
456
+ {
457
+ effect: 'Allow' | 'Deny',
458
+ actions: ['s3:GetObject', 's3:PutObject'],
459
+ resources?: ['arn:aws:s3:::meu-bucket/*'],
460
+ conditions?: Record<string, Record<string, string>>,
461
+ }
462
+ ],
463
+ });
464
+ export default stack;
465
+ \`\`\`
466
+
467
+ ---
468
+ ## EVENTS & WORKFLOW
469
+
470
+ ### Events.EventBridge \u2014 EventBridge / Event Grid / Pub/Sub
471
+ \`\`\`typescript
472
+ import { Stack, Events } from '@iacmp/core';
473
+ const stack = new Stack('nome');
474
+ new Events.EventBridge(stack, 'LogicalId', {
475
+ busName?: string,
476
+ description?: string,
477
+ rules?: [
478
+ {
479
+ name: string,
480
+ source?: string[],
481
+ detailTypes?: string[],
482
+ targetArn?: string,
483
+ description?: string,
484
+ }
485
+ ],
486
+ });
487
+ export default stack;
488
+ \`\`\`
489
+
490
+ ### Workflow.StepFunctions \u2014 Step Functions / Logic Apps / Cloud Workflows
491
+ \`\`\`typescript
492
+ import { Stack, Workflow } from '@iacmp/core';
493
+ const stack = new Stack('nome');
494
+ new Workflow.StepFunctions(stack, 'LogicalId', {
495
+ type?: 'STANDARD' | 'EXPRESS',
496
+ description?: string,
497
+ steps: [
498
+ {
499
+ name: string,
500
+ type?: 'Task' | 'Choice' | 'Wait' | 'Parallel' | 'Map' | 'Pass' | 'Succeed' | 'Fail',
501
+ resource?: string,
502
+ description?: string,
503
+ }
504
+ ],
505
+ });
506
+ export default stack;
507
+ \`\`\`
508
+
509
+ ---
510
+ ## MESSAGING
511
+
512
+ ### Messaging.Queue \u2014 SQS / Service Bus Queue / Cloud Tasks
513
+ \`\`\`typescript
514
+ import { Stack, Messaging } from '@iacmp/core';
515
+ const stack = new Stack('nome');
516
+ new Messaging.Queue(stack, 'LogicalId', {
517
+ visibilityTimeoutSeconds?: number,
518
+ messageRetentionSeconds?: number,
519
+ delaySeconds?: number,
520
+ fifo?: boolean,
521
+ encrypted?: boolean,
522
+ dlqArn?: string,
523
+ maxReceiveCount?: number,
524
+ });
525
+ export default stack;
526
+ \`\`\`
527
+
528
+ ### Messaging.Topic \u2014 SNS / Service Bus Topic / Pub/Sub Topic
529
+ \`\`\`typescript
530
+ import { Stack, Messaging } from '@iacmp/core';
531
+ const stack = new Stack('nome');
532
+ new Messaging.Topic(stack, 'LogicalId', {
533
+ displayName?: string,
534
+ fifo?: boolean,
535
+ encrypted?: boolean,
536
+ subscriptions?: [
537
+ { protocol: 'lambda' | 'sqs' | 'email' | 'http' | 'https', endpoint: string }
538
+ ],
539
+ });
540
+ export default stack;
541
+ \`\`\`
542
+
543
+ ---
544
+ ## SECRET & CERTIFICATE
545
+
546
+ ### Secret.Vault \u2014 Secrets Manager / Key Vault / Secret Manager
547
+ \`\`\`typescript
548
+ import { Stack, Secret } from '@iacmp/core';
549
+ const stack = new Stack('nome');
550
+ new Secret.Vault(stack, 'LogicalId', {
551
+ description?: string,
552
+ kmsKeyId?: string,
553
+ rotationDays?: number,
554
+ replicaRegions?: string[],
555
+ });
556
+ export default stack;
557
+ \`\`\`
558
+
559
+ ### Certificate.TLS \u2014 ACM / Key Vault Cert / Certificate Manager
560
+ \`\`\`typescript
561
+ import { Stack, Certificate } from '@iacmp/core';
562
+ const stack = new Stack('nome');
563
+ new Certificate.TLS(stack, 'LogicalId', {
564
+ domainName: string, // obrigat\xF3rio: ex 'api.example.com'
565
+ subjectAlternativeNames?: string[],
566
+ validationMethod?: 'DNS' | 'EMAIL',
567
+ region?: string,
568
+ });
569
+ export default stack;
570
+ \`\`\`
571
+
572
+ ---
573
+ ## MONITORING
574
+
575
+ ### Monitoring.Alarm \u2014 CloudWatch Alarm / Azure Monitor / Cloud Monitoring
576
+ \`\`\`typescript
577
+ import { Stack, Monitoring } from '@iacmp/core';
578
+ const stack = new Stack('nome');
579
+ new Monitoring.Alarm(stack, 'LogicalId', {
580
+ metricName: string, // obrigat\xF3rio
581
+ namespace?: string, // ex: 'AWS/Lambda'
582
+ threshold: number, // obrigat\xF3rio
583
+ evaluationPeriods?: number,
584
+ periodSeconds?: number,
585
+ comparisonOperator?: 'GreaterThanThreshold' | 'LessThanThreshold' | 'GreaterThanOrEqualToThreshold' | 'LessThanOrEqualToThreshold',
586
+ statistic?: 'Average' | 'Sum' | 'Minimum' | 'Maximum' | 'SampleCount',
587
+ treatMissingData?: 'notBreaching' | 'breaching' | 'ignore' | 'missing',
588
+ alarmActions?: string[],
589
+ okActions?: string[],
590
+ dimensions?: Record<string, string>,
591
+ });
592
+ export default stack;
593
+ \`\`\`
594
+
595
+ ### Monitoring.Dashboard \u2014 CloudWatch Dashboard
596
+ \`\`\`typescript
597
+ new Monitoring.Dashboard(stack, 'LogicalId', {
598
+ widgets: [
599
+ {
600
+ type: 'metric' | 'text' | 'alarm',
601
+ title?: string,
602
+ metricName?: string,
603
+ namespace?: string,
604
+ period?: number,
605
+ stat?: string,
606
+ markdown?: string, // para type: 'text'
607
+ }
608
+ ],
609
+ });
610
+ \`\`\`
611
+
612
+ ### Logging.Stream \u2014 CloudWatch Log Group / Log Analytics / Cloud Logging
613
+ \`\`\`typescript
614
+ import { Stack, Logging } from '@iacmp/core';
615
+ const stack = new Stack('nome');
616
+ new Logging.Stream(stack, 'LogicalId', {
617
+ retentionDays?: number, // padr\xE3o: 30
618
+ kmsKeyId?: string,
619
+ subscriptionFilters?: [
620
+ {
621
+ name: string,
622
+ filterPattern: string,
623
+ destinationArn: string,
624
+ }
625
+ ],
626
+ });
627
+ export default stack;
628
+ \`\`\`
629
+
630
+ ---
631
+ ## CUSTOM \u2014 escape hatch para servi\xE7os fora do cat\xE1logo
632
+
633
+ ### Custom.Resource \u2014 qualquer recurso nativo do provider sem construct tipado
634
+
635
+ Quando o usu\xE1rio pedir um servi\xE7o/recurso que n\xE3o tem construct dedicado no cat\xE1logo acima (ex: Secrets Manager rotation schedule, Static Web App, Pub/Sub topic avulso, qualquer recurso bem espec\xEDfico de um provider), N\xC3O recuse e N\xC3O diga apenas "n\xE3o existe construct para isso". Gere o recurso nativo real usando \`Custom.Resource\`, preenchendo APENAS a chave do formato de sa\xEDda relevante ao provider da stack:
636
+
637
+ \`\`\`typescript
638
+ import { Stack, Custom } from '@iacmp/core';
639
+ const stack = new Stack('nome');
640
+
641
+ new Custom.Resource(stack, 'LogicalId', {
642
+ description?: string,
643
+
644
+ // AWS (gera AWS::SecretsManager::RotationSchedule etc. no CloudFormation)
645
+ cloudformation?: { type: string, properties: Record<string, unknown> },
646
+
647
+ // Azure (gera Microsoft.Web/staticSites etc. no ARM Template)
648
+ arm?: { type: string, apiVersion: string, properties: Record<string, unknown>, sku?: Record<string, unknown>, kind?: string },
649
+
650
+ // GCP (gera pubsub.v1.topic etc. no Deployment Manager)
651
+ deploymentManager?: { type: string, properties: Record<string, unknown> },
652
+
653
+ // Terraform (gera resource "aws_secretsmanager_rotation_schedule" "LogicalId" {...})
654
+ terraform?: { type: string, body: Record<string, unknown> },
655
+ });
656
+ export default stack;
657
+ \`\`\`
658
+
659
+ Regras:
660
+ 1. Preencha apenas a(s) chave(s) do(s) formato(s) que a stack realmente vai sintetizar (normalmente CloudFormation+Terraform para AWS, ARM para Azure, Deployment Manager para GCP) \u2014 n\xE3o precisa preencher as 4 se a stack s\xF3 usa um provider.
661
+ 2. Use a sintaxe e os nomes de campo REAIS do formato nativo (ex: \`AWS::SecretsManager::RotationSchedule\` com PascalCase nas properties para CloudFormation; \`secret_id\`/\`rotation_rules\` em snake_case para Terraform). Voc\xEA j\xE1 conhece essas APIs \u2014 use esse conhecimento em vez de inventar campos gen\xE9ricos.
662
+ 3. Para referenciar outro recurso da mesma stack: no \`terraform.body\`, use a refer\xEAncia crua como string (ex: \`"aws_secretsmanager_secret.MySecret.id"\`) \u2014 ela \xE9 emitida sem aspas automaticamente quando cont\xE9m um ponto. No \`cloudformation.properties\`, use \`{ Ref: 'LogicalId' }\` ou \`{ 'Fn::GetAtt': [...] }\` normalmente.
663
+ 4. Isso \xE9 um escape hatch, n\xE3o o caminho padr\xE3o \u2014 se existe construct tipado para o que o usu\xE1rio pediu (Fn.Lambda, Database.SQL, etc.), use o construct tipado.
664
+
665
+ ---
666
+ ## Regra de integra\xE7\xE3o entre stacks
667
+ Quando o usu\xE1rio pedir uma stack que depende de recursos de outra stack j\xE1 existente (ex: Lambda que l\xEA de um DynamoDB existente):
668
+ - NUNCA recrie o recurso j\xE1 existente na nova stack
669
+ - Referencie via vari\xE1vel de ambiente (ex: TABLE_NAME) usando o nome l\xF3gico do recurso
670
+ - Mencione na "explanation" qual stack existente est\xE1 sendo referenciada e por qu\xEA
671
+
672
+ ## Tamanhos de inst\xE2ncia
673
+ - \`small\` \u2192 t3.small / cache.t3.micro / B1s / e2-small
674
+ - \`medium\` \u2192 t3.medium / cache.t3.medium / B2s / e2-medium
675
+ - \`large\` \u2192 t3.large / cache.r6g.large / B4ms / e2-standard-4
676
+
677
+ ## Regras de gera\xE7\xE3o de c\xF3digo
678
+ 1. SEMPRE use apenas constructs do @iacmp/core listados acima \u2014 nunca invente propriedades extras
679
+ 2. SEMPRE exporte a stack como default: \`export default stack;\`
680
+ 3. Nomeie o arquivo em kebab-case com sufixo \`-stack.ts\` e coloque na subpasta correta:
681
+ - \`stacks/compute/\` \u2192 Compute.*, Fn.Lambda
682
+ - \`stacks/database/\` \u2192 Database.SQL, Database.DocumentDB, Database.DynamoDB, Cache.Redis, Cache.Memcached
683
+ - \`stacks/storage/\` \u2192 Storage.Bucket, Storage.FileSystem, Storage.Archive
684
+ - \`stacks/network/\` \u2192 Network.VPC, Network.Subnet, Network.SecurityGroup, Network.WAF, Network.LoadBalancer, Network.CDN, Network.Dns, Function.ApiGateway
685
+ - \`stacks/messaging/\` \u2192 Messaging.Queue, Messaging.Topic, Events.EventBridge
686
+ - \`stacks/workflow/\` \u2192 Workflow.StepFunctions
687
+ - \`stacks/policy/\` \u2192 Policy.IAM
688
+ - \`stacks/security/\` \u2192 Secret.Vault, Certificate.TLS
689
+ - \`stacks/monitoring/\` \u2192 Monitoring.Alarm, Monitoring.Dashboard, Logging.Stream
690
+ 4. N\xE3o adicione coment\xE1rios desnecess\xE1rios
691
+ 5. N\xE3o gere arquivos al\xE9m da stack (sem package.json, tsconfig.json, etc.) a menos que seja explicitamente pedido
692
+
693
+ ## Formato de resposta OBRIGAT\xD3RIO
694
+ Responda SEMPRE com JSON puro, sem markdown, sem blocos de c\xF3digo, sem texto antes ou depois.
695
+ Isso vale para QUALQUER tipo de mensagem \u2014 pergunta, explica\xE7\xE3o, erro, d\xFAvida, conversa.
696
+
697
+ {
698
+ "explanation": "Descri\xE7\xE3o clara do que ser\xE1 criado/removido e por qu\xEA \u2014 ou a resposta \xE0 pergunta do usu\xE1rio",
699
+ "files": [],
700
+ "deletions": [],
701
+ "nextSteps": [],
702
+ "warnings": []
703
+ }
704
+
705
+ Exemplos de como responder perguntas conversacionais:
706
+
707
+ Pergunta: "por que voc\xEA usou postgres em vez de oracle?"
708
+ Resposta correta:
709
+ {"explanation":"O construct Database.SQL suporta os engines 'mysql', 'postgres', 'mariadb', 'oracle' e 'sqlserver'. Se preferir Oracle, posso alterar o stack para usar engine: 'oracle'. No GCP, Oracle n\xE3o tem servi\xE7o gerenciado nativo e ser\xE1 provisionado como PostgreSQL (AlloyDB-compatible); nas outras clouds (AWS e Azure) o Oracle \xE9 nativo.","files":[],"deletions":[],"nextSteps":[],"warnings":[]}
710
+
711
+ Pergunta: "o que \xE9 um NAT Gateway?"
712
+ Resposta correta:
713
+ {"explanation":"NAT Gateway permite que inst\xE2ncias em subnets privadas acessem a internet sem serem acess\xEDveis de fora. No @iacmp/core, ao criar uma Network.VPC, subnets privadas recebem NAT Gateway automaticamente quando maxAzs > 0.","files":[],"deletions":[],"nextSteps":[],"warnings":[]}
714
+
715
+ - \`files\`: arquivos a criar ou modificar \u2014 VAZIO quando for s\xF3 uma resposta explicativa
716
+ - \`deletions\`: caminhos de arquivos a REMOVER. O CLI remove o .ts e o synth-out correspondente automaticamente, e limpa refer\xEAncias em outros arquivos.
717
+ - \`warnings\`: alertas sobre custo alto, breaking changes ou limita\xE7\xF5es
718
+
719
+ ## Remo\xE7\xE3o de stacks
720
+ Quando o usu\xE1rio pedir para remover uma stack:
721
+ - Use o campo \`deletions\` com o caminho exato do arquivo .ts
722
+ - Deixe \`files\` vazio se for s\xF3 remo\xE7\xE3o
723
+ - NUNCA oriente o usu\xE1rio a rodar \`rm\` ou \`iacmp destroy\` manualmente \u2014 o CLI cuida disso automaticamente
724
+ - N\xC3O inclua \`iacmp destroy\` nos \`nextSteps\`
725
+
726
+ ## Acesso ao projeto \u2014 REGRAS CR\xCDTICAS
727
+ O CLI injeta automaticamente o contexto completo do projeto neste prompt, incluindo o conte\xFAdo de todos os arquivos em stacks/. Isso significa:
728
+
729
+ 1. NUNCA pe\xE7a ao usu\xE1rio para colar c\xF3digo \u2014 voc\xEA j\xE1 tem acesso a todo o conte\xFAdo dos arquivos
730
+ 2. NUNCA sugira comandos como "cat stacks/arquivo.ts e cole aqui"
731
+ 3. Se o usu\xE1rio reportar um erro em um arquivo, leia o conte\xFAdo dispon\xEDvel no contexto abaixo e corrija diretamente
732
+ 4. Se um arquivo n\xE3o aparecer no contexto, significa que ainda n\xE3o existe \u2014 crie-o
733
+ 5. Para corrigir erros: gere o arquivo corrigido completo no campo "files" do JSON de resposta
734
+ 6. Se a se\xE7\xE3o "Stacks existentes" aparecer abaixo com arquivos listados, voc\xEA EST\xC1 em modo de projeto \u2014 NUNCA diga "modo standalone", NUNCA diga que n\xE3o tem acesso aos arquivos, NUNCA pe\xE7a ao usu\xE1rio para descrever a estrutura do projeto do zero
735
+
736
+ ## Modifica\xE7\xE3o de stacks existentes \u2014 REGRAS INVIOL\xC1VEIS
737
+
738
+ Antes de gerar qualquer arquivo, leia a se\xE7\xE3o "Stacks existentes" no contexto do projeto.
739
+
740
+ 6. Se o usu\xE1rio pedir para MOVER um recurso (ex: "coloca na stack do api gateway"), identifique qual arquivo j\xE1 existe para aquela stack e modifique-o \u2014 NUNCA crie um arquivo novo com outro nome
741
+ 7. Se o usu\xE1rio pedir para ADICIONAR um recurso a uma stack existente, gere o arquivo existente com o novo recurso inclu\xEDdo
742
+ 8. Se j\xE1 existir um arquivo de ApiGateway, Lambda, Database etc., qualquer mudan\xE7a nesse tipo de recurso vai naquele arquivo \u2014 n\xE3o em um arquivo novo
743
+ 9. O caminho do arquivo no campo "path" deve ser ID\xCANTICO ao caminho listado em "Stacks existentes" \u2014 nunca invente um caminho diferente para um arquivo que j\xE1 existe
744
+ 10. Quando houver d\xFAvida sobre qual arquivo usar, prefira o que j\xE1 existe a criar um novo
745
+
746
+ ## Quando o usu\xE1rio discorda ou corrige algo que voc\xEA gerou
747
+
748
+ 1. Releia a mensagem anterior sua antes de responder \u2014 se voc\xEA concordou com o ponto do usu\xE1rio, a resposta TEM que conter uma mudan\xE7a real em "files" ou "deletions", nunca apenas um texto reafirmando que "est\xE1 adequado" ou "n\xE3o h\xE1 nada a corrigir"
749
+ 2. NUNCA d\xEA uma explica\xE7\xE3o que se contradiz dentro do mesmo texto (ex: dizer que algo "deveria ser diferente" e na frase seguinte dizer que "est\xE1 correto como est\xE1") \u2014 decida um lado e aja de acordo
750
+ 3. Se voc\xEA concorda que havia um problema, gere o arquivo corrigido em "files". Se voc\xEA discorda do usu\xE1rio, explique objetivamente o motivo t\xE9cnico da discord\xE2ncia e n\xE3o gere nenhum arquivo \u2014 mas nunca as duas coisas ao mesmo tempo
751
+ 4. Se n\xE3o tiver certeza de como resolver o que o usu\xE1rio pediu (ex: falta um construct no @iacmp/core para a solu\xE7\xE3o ideal), diga isso explicitamente e pergunte como proceder, em vez de alegar que o estado atual j\xE1 est\xE1 correto
752
+
753
+ ## Contexto do projeto atual
754
+ {PROJECT_CONTEXT}`;
755
+ function buildSystemPrompt2(projectContext) {
756
+ return exports2.SYSTEM_PROMPT_TEMPLATE.replace("{PROJECT_CONTEXT}", projectContext);
757
+ }
758
+ exports2.SYSTEM_PROMPT = exports2.SYSTEM_PROMPT_TEMPLATE.replace("{PROJECT_CONTEXT}", "Nenhum projeto carregado \u2014 modo standalone.");
759
+ }
760
+ });
761
+
762
+ // ../ai/dist/providers/retry.js
763
+ var require_retry = __commonJS({
764
+ "../ai/dist/providers/retry.js"(exports2) {
765
+ "use strict";
766
+ Object.defineProperty(exports2, "__esModule", { value: true });
767
+ exports2.withRetry = withRetry;
768
+ function isRetryable(err) {
769
+ if (err?.noRetry)
770
+ return false;
771
+ const status = err?.status;
772
+ if (status === 429 || status === 500 || status === 502 || status === 503 || status === 504)
773
+ return true;
774
+ const code = err?.code;
775
+ if (code === "ECONNRESET" || code === "ETIMEDOUT")
776
+ return true;
777
+ return false;
778
+ }
779
+ async function withRetry(fn, maxAttempts = 3) {
780
+ let lastErr;
781
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
782
+ try {
783
+ return await fn();
784
+ } catch (err) {
785
+ lastErr = err;
786
+ if (attempt === maxAttempts || !isRetryable(err))
787
+ throw err;
788
+ const delayMs = 500 * 2 ** (attempt - 1);
789
+ await new Promise((resolve2) => setTimeout(resolve2, delayMs));
790
+ }
791
+ }
792
+ throw lastErr;
793
+ }
794
+ }
795
+ });
796
+
797
+ // ../ai/dist/providers/anthropic.js
798
+ var require_anthropic = __commonJS({
799
+ "../ai/dist/providers/anthropic.js"(exports2) {
800
+ "use strict";
801
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
802
+ return mod && mod.__esModule ? mod : { "default": mod };
803
+ };
804
+ Object.defineProperty(exports2, "__esModule", { value: true });
805
+ exports2.AnthropicProvider = void 0;
806
+ var sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
807
+ var system_prompt_1 = require_system_prompt();
808
+ var retry_1 = require_retry();
809
+ var AnthropicProvider2 = class {
810
+ name = "anthropic";
811
+ client;
812
+ constructor(apiKey) {
813
+ this.client = new sdk_1.default({ apiKey });
814
+ }
815
+ async chat(messages) {
816
+ const filtered = messages.filter((m) => m.role !== "system").map((m) => ({ role: m.role, content: m.content }));
817
+ const response = await (0, retry_1.withRetry)(() => this.client.messages.create({
818
+ model: "claude-sonnet-4-6",
819
+ max_tokens: 8192,
820
+ system: system_prompt_1.SYSTEM_PROMPT,
821
+ messages: filtered
822
+ }));
823
+ const block = response.content[0];
824
+ return {
825
+ content: block.type === "text" ? block.text : "",
826
+ usage: {
827
+ inputTokens: response.usage.input_tokens,
828
+ outputTokens: response.usage.output_tokens
829
+ }
830
+ };
831
+ }
832
+ async stream(messages, onChunk) {
833
+ const filtered = messages.filter((m) => m.role !== "system").map((m) => ({ role: m.role, content: m.content }));
834
+ let emittedAny = false;
835
+ await (0, retry_1.withRetry)(async () => {
836
+ if (emittedAny)
837
+ throw Object.assign(new Error("stream interrompido ap\xF3s in\xEDcio \u2014 sem retry"), { noRetry: true });
838
+ const stream = this.client.messages.stream({
839
+ model: "claude-sonnet-4-6",
840
+ max_tokens: 8192,
841
+ system: system_prompt_1.SYSTEM_PROMPT,
842
+ messages: filtered
843
+ });
844
+ for await (const chunk of stream) {
845
+ if (chunk.type === "content_block_delta" && chunk.delta.type === "text_delta") {
846
+ emittedAny = true;
847
+ onChunk(chunk.delta.text);
848
+ }
849
+ }
850
+ });
851
+ }
852
+ };
853
+ exports2.AnthropicProvider = AnthropicProvider2;
854
+ }
855
+ });
856
+
857
+ // ../ai/dist/providers/copilot.js
858
+ var require_copilot = __commonJS({
859
+ "../ai/dist/providers/copilot.js"(exports2) {
860
+ "use strict";
861
+ Object.defineProperty(exports2, "__esModule", { value: true });
862
+ exports2.CopilotProvider = void 0;
863
+ var system_prompt_1 = require_system_prompt();
864
+ var retry_1 = require_retry();
865
+ var COPILOT_ENDPOINT = "https://api.githubcopilot.com/chat/completions";
866
+ var CopilotProvider2 = class {
867
+ name = "copilot";
868
+ token;
869
+ constructor(token) {
870
+ this.token = token;
871
+ }
872
+ buildMessages(messages) {
873
+ const result = [
874
+ { role: "system", content: system_prompt_1.SYSTEM_PROMPT }
875
+ ];
876
+ for (const m of messages) {
877
+ if (m.role !== "system") {
878
+ result.push({ role: m.role, content: m.content });
879
+ }
880
+ }
881
+ return result;
882
+ }
883
+ async chat(messages) {
884
+ return (0, retry_1.withRetry)(async () => {
885
+ const response = await fetch(COPILOT_ENDPOINT, {
886
+ method: "POST",
887
+ headers: {
888
+ "Authorization": `Bearer ${this.token}`,
889
+ "Content-Type": "application/json",
890
+ "Copilot-Integration-Id": "iacmp-cli"
891
+ },
892
+ body: JSON.stringify({
893
+ model: "gpt-4o",
894
+ messages: this.buildMessages(messages),
895
+ max_tokens: 8192
896
+ })
897
+ });
898
+ if (!response.ok) {
899
+ const text = await response.text();
900
+ throw Object.assign(new Error(`Copilot API error ${response.status}: ${text}`), { status: response.status });
901
+ }
902
+ const data = await response.json();
903
+ return {
904
+ content: data.choices[0].message.content,
905
+ usage: {
906
+ inputTokens: data.usage.prompt_tokens,
907
+ outputTokens: data.usage.completion_tokens
908
+ }
909
+ };
910
+ });
911
+ }
912
+ async stream(messages, onChunk) {
913
+ let emittedAny = false;
914
+ await (0, retry_1.withRetry)(async () => {
915
+ if (emittedAny)
916
+ throw Object.assign(new Error("stream interrompido ap\xF3s in\xEDcio \u2014 sem retry"), { noRetry: true });
917
+ const response = await fetch(COPILOT_ENDPOINT, {
918
+ method: "POST",
919
+ headers: {
920
+ "Authorization": `Bearer ${this.token}`,
921
+ "Content-Type": "application/json",
922
+ "Copilot-Integration-Id": "iacmp-cli"
923
+ },
924
+ body: JSON.stringify({
925
+ model: "gpt-4o",
926
+ messages: this.buildMessages(messages),
927
+ max_tokens: 8192,
928
+ stream: true
929
+ })
930
+ });
931
+ if (!response.ok) {
932
+ const text = await response.text();
933
+ throw Object.assign(new Error(`Copilot API error ${response.status}: ${text}`), { status: response.status });
934
+ }
935
+ if (!response.body) {
936
+ throw new Error("Copilot: response body vazio");
937
+ }
938
+ const reader = response.body.getReader();
939
+ const decoder = new TextDecoder();
940
+ while (true) {
941
+ const { done, value } = await reader.read();
942
+ if (done)
943
+ break;
944
+ const raw = decoder.decode(value);
945
+ const lines = raw.split("\n").filter((l) => l.startsWith("data: "));
946
+ for (const line of lines) {
947
+ const json = line.slice(6).trim();
948
+ if (json === "[DONE]")
949
+ return;
950
+ try {
951
+ const parsed = JSON.parse(json);
952
+ const text = parsed.choices?.[0]?.delta?.content ?? "";
953
+ if (text) {
954
+ emittedAny = true;
955
+ onChunk(text);
956
+ }
957
+ } catch {
958
+ }
959
+ }
960
+ }
961
+ });
962
+ }
963
+ };
964
+ exports2.CopilotProvider = CopilotProvider2;
965
+ }
966
+ });
967
+
968
+ // ../ai/dist/parser/code-extractor.js
969
+ var require_code_extractor = __commonJS({
970
+ "../ai/dist/parser/code-extractor.js"(exports2) {
971
+ "use strict";
972
+ Object.defineProperty(exports2, "__esModule", { value: true });
973
+ exports2.MAX_FILE_BYTES = exports2.MAX_DELETIONS = exports2.MAX_FILES = void 0;
974
+ exports2.extractResponse = extractResponse2;
975
+ exports2.MAX_FILES = 50;
976
+ exports2.MAX_DELETIONS = 100;
977
+ exports2.MAX_FILE_BYTES = 256 * 1024;
978
+ function extractResponse2(raw) {
979
+ const trimmed = raw.trim();
980
+ const direct = tryParse(trimmed);
981
+ if (direct)
982
+ return validate(direct);
983
+ const codeBlock = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/);
984
+ if (codeBlock) {
985
+ const parsed = tryParse(codeBlock[1].trim());
986
+ if (parsed)
987
+ return validate(parsed);
988
+ }
989
+ const firstBrace = trimmed.indexOf("{");
990
+ const lastBrace = trimmed.lastIndexOf("}");
991
+ if (firstBrace !== -1 && lastBrace > firstBrace) {
992
+ const slice = trimmed.slice(firstBrace, lastBrace + 1);
993
+ const parsed = tryParse(slice);
994
+ if (parsed)
995
+ return validate(parsed);
996
+ }
997
+ throw new Error("N\xE3o foi poss\xEDvel extrair JSON do response da IA.\nResponse recebido:\n" + trimmed.slice(0, 300) + (trimmed.length > 300 ? "..." : ""));
998
+ }
999
+ function tryParse(text) {
1000
+ try {
1001
+ return JSON.parse(text);
1002
+ } catch {
1003
+ return null;
1004
+ }
1005
+ }
1006
+ function validate(obj) {
1007
+ if (typeof obj !== "object" || obj === null) {
1008
+ throw new Error("Response da IA n\xE3o \xE9 um objeto JSON v\xE1lido.");
1009
+ }
1010
+ const o = obj;
1011
+ if (typeof o["explanation"] !== "string") {
1012
+ throw new Error('Response da IA est\xE1 faltando o campo "explanation" (string).');
1013
+ }
1014
+ if (!Array.isArray(o["files"])) {
1015
+ throw new Error('Response da IA est\xE1 faltando o campo "files" (array).');
1016
+ }
1017
+ const rawFiles = o["files"];
1018
+ if (rawFiles.length > exports2.MAX_FILES) {
1019
+ throw new Error(`Response da IA excede o limite de arquivos: ${rawFiles.length} > ${exports2.MAX_FILES}. Reduza o escopo da requisi\xE7\xE3o.`);
1020
+ }
1021
+ const files = [];
1022
+ for (const f of rawFiles) {
1023
+ if (typeof f !== "object" || f === null) {
1024
+ throw new Error('Cada item em "files" deve ser um objeto com "path" e "content".');
1025
+ }
1026
+ const file = f;
1027
+ if (typeof file["path"] !== "string" || typeof file["content"] !== "string") {
1028
+ throw new Error('Cada arquivo deve ter "path" (string) e "content" (string).');
1029
+ }
1030
+ const byteLen = Buffer.byteLength(file["content"], "utf-8");
1031
+ if (byteLen > exports2.MAX_FILE_BYTES) {
1032
+ throw new Error(`Arquivo "${file["path"]}" excede o limite de tamanho: ${byteLen} bytes > ${exports2.MAX_FILE_BYTES} bytes. Divida o conte\xFAdo em arquivos menores.`);
1033
+ }
1034
+ files.push({ path: file["path"], content: file["content"] });
1035
+ }
1036
+ const rawDeletions = Array.isArray(o["deletions"]) ? o["deletions"].filter((s) => typeof s === "string") : [];
1037
+ if (rawDeletions.length > exports2.MAX_DELETIONS) {
1038
+ throw new Error(`Response da IA excede o limite de remo\xE7\xF5es: ${rawDeletions.length} > ${exports2.MAX_DELETIONS}. Reduza o escopo da requisi\xE7\xE3o.`);
1039
+ }
1040
+ return {
1041
+ explanation: o["explanation"],
1042
+ files,
1043
+ deletions: rawDeletions,
1044
+ nextSteps: Array.isArray(o["nextSteps"]) ? o["nextSteps"].filter((s) => typeof s === "string") : [],
1045
+ warnings: Array.isArray(o["warnings"]) ? o["warnings"].filter((s) => typeof s === "string") : []
1046
+ };
1047
+ }
1048
+ }
1049
+ });
1050
+
1051
+ // ../ai/dist/parser/validator.js
1052
+ var require_validator = __commonJS({
1053
+ "../ai/dist/parser/validator.js"(exports2) {
1054
+ "use strict";
1055
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
1056
+ if (k2 === void 0) k2 = k;
1057
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1058
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1059
+ desc = { enumerable: true, get: function() {
1060
+ return m[k];
1061
+ } };
1062
+ }
1063
+ Object.defineProperty(o, k2, desc);
1064
+ }) : (function(o, m, k, k2) {
1065
+ if (k2 === void 0) k2 = k;
1066
+ o[k2] = m[k];
1067
+ }));
1068
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
1069
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1070
+ }) : function(o, v) {
1071
+ o["default"] = v;
1072
+ });
1073
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
1074
+ var ownKeys = function(o) {
1075
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1076
+ var ar = [];
1077
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1078
+ return ar;
1079
+ };
1080
+ return ownKeys(o);
1081
+ };
1082
+ return function(mod) {
1083
+ if (mod && mod.__esModule) return mod;
1084
+ var result = {};
1085
+ if (mod != null) {
1086
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1087
+ }
1088
+ __setModuleDefault(result, mod);
1089
+ return result;
1090
+ };
1091
+ })();
1092
+ Object.defineProperty(exports2, "__esModule", { value: true });
1093
+ exports2.validateTypeScript = validateTypeScript2;
1094
+ var fs2 = __importStar(require("fs"));
1095
+ var path2 = __importStar(require("path"));
1096
+ var os = __importStar(require("os"));
1097
+ var child_process_1 = require("child_process");
1098
+ function validateTypeScript2(files, projectDir) {
1099
+ const tmpDir = fs2.mkdtempSync(path2.join(os.tmpdir(), "iacmp-validate-"));
1100
+ try {
1101
+ for (const file of files) {
1102
+ const filePath = path2.join(tmpDir, path2.basename(file.path));
1103
+ fs2.writeFileSync(filePath, file.content, "utf-8");
1104
+ }
1105
+ const coreTypesPath = (function findCoreTypes() {
1106
+ const candidates2 = [
1107
+ // monorepo local (dev)
1108
+ path2.resolve(__dirname, "..", "..", "..", "core", "dist"),
1109
+ // node_modules do CLI instalado globalmente
1110
+ path2.resolve(__dirname, "..", "..", "node_modules", "@iacmp", "core", "dist"),
1111
+ // node_modules do projeto do usuário
1112
+ path2.join(projectDir, "node_modules", "@iacmp", "core", "dist")
1113
+ ];
1114
+ for (const c of candidates2) {
1115
+ if (fs2.existsSync(path2.join(c, "index.d.ts")))
1116
+ return c;
1117
+ }
1118
+ return null;
1119
+ })();
1120
+ const tsconfigPaths = {};
1121
+ if (coreTypesPath) {
1122
+ tsconfigPaths["@iacmp/core"] = [path2.join(coreTypesPath, "index.d.ts")];
1123
+ tsconfigPaths["@iacmp/core/*"] = [path2.join(coreTypesPath, "*")];
1124
+ }
1125
+ const tsconfig = {
1126
+ compilerOptions: {
1127
+ target: "ES2022",
1128
+ module: "commonjs",
1129
+ moduleResolution: "node",
1130
+ esModuleInterop: true,
1131
+ strict: false,
1132
+ skipLibCheck: true,
1133
+ noEmit: true,
1134
+ baseUrl: "/",
1135
+ paths: tsconfigPaths
1136
+ },
1137
+ include: [path2.join(tmpDir, "*.ts")]
1138
+ };
1139
+ fs2.writeFileSync(path2.join(tmpDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2), "utf-8");
1140
+ const candidates = [
1141
+ path2.join(projectDir, "node_modules", ".bin", "tsc"),
1142
+ path2.resolve(__dirname, "..", "..", "node_modules", ".bin", "tsc"),
1143
+ path2.resolve(__dirname, "..", "..", "..", "..", "node_modules", ".bin", "tsc")
1144
+ ];
1145
+ const tscPath = candidates.find((c) => fs2.existsSync(c));
1146
+ if (!tscPath) {
1147
+ return { valid: true, errors: [] };
1148
+ }
1149
+ (0, child_process_1.execSync)(`${tscPath} --noEmit --project ${path2.join(tmpDir, "tsconfig.json")}`, {
1150
+ cwd: tmpDir,
1151
+ stdio: "pipe"
1152
+ });
1153
+ return { valid: true, errors: [] };
1154
+ } catch (err) {
1155
+ const error = err;
1156
+ if (error.code === "ENOENT") {
1157
+ return { valid: true, errors: [] };
1158
+ }
1159
+ const output = (error.stdout?.toString() ?? "") + (error.stderr?.toString() ?? "");
1160
+ const errors = output.split("\n").filter((l) => l.trim().length > 0).slice(0, 20);
1161
+ return { valid: false, errors };
1162
+ } finally {
1163
+ try {
1164
+ fs2.rmSync(tmpDir, { recursive: true, force: true });
1165
+ } catch {
1166
+ }
1167
+ }
1168
+ }
1169
+ }
1170
+ });
1171
+
1172
+ // ../ai/dist/chat/session.js
1173
+ var require_session = __commonJS({
1174
+ "../ai/dist/chat/session.js"(exports2) {
1175
+ "use strict";
1176
+ Object.defineProperty(exports2, "__esModule", { value: true });
1177
+ exports2.ChatSession = void 0;
1178
+ var ChatSession2 = class {
1179
+ messages = [];
1180
+ addUserMessage(content) {
1181
+ this.messages.push({ role: "user", content });
1182
+ }
1183
+ addAssistantMessage(content) {
1184
+ this.messages.push({ role: "assistant", content });
1185
+ }
1186
+ getMessages() {
1187
+ return [...this.messages];
1188
+ }
1189
+ removeLast() {
1190
+ this.messages.pop();
1191
+ }
1192
+ clear() {
1193
+ this.messages = [];
1194
+ }
1195
+ };
1196
+ exports2.ChatSession = ChatSession2;
1197
+ }
1198
+ });
1199
+
1200
+ // ../ai/dist/chat/renderer.js
1201
+ var require_renderer = __commonJS({
1202
+ "../ai/dist/chat/renderer.js"(exports2) {
1203
+ "use strict";
1204
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
1205
+ return mod && mod.__esModule ? mod : { "default": mod };
1206
+ };
1207
+ Object.defineProperty(exports2, "__esModule", { value: true });
1208
+ exports2.printThinking = printThinking;
1209
+ exports2.stopThinking = stopThinking;
1210
+ exports2.printExplanation = printExplanation2;
1211
+ exports2.printWarnings = printWarnings2;
1212
+ exports2.printNextSteps = printNextSteps2;
1213
+ exports2.printStreamChunk = printStreamChunk;
1214
+ var chalk_1 = __importDefault(require("chalk"));
1215
+ var ora_1 = __importDefault(require("ora"));
1216
+ var activeSpinner = null;
1217
+ function printThinking() {
1218
+ activeSpinner = (0, ora_1.default)({ text: "Gerando stack...", color: "cyan" }).start();
1219
+ return activeSpinner;
1220
+ }
1221
+ function stopThinking() {
1222
+ if (activeSpinner) {
1223
+ activeSpinner.stop();
1224
+ activeSpinner = null;
1225
+ }
1226
+ }
1227
+ function printExplanation2(text) {
1228
+ console.log("\n" + chalk_1.default.cyan.bold("\u2500\u2500\u2500 Explica\xE7\xE3o \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1229
+ console.log(chalk_1.default.white(text));
1230
+ console.log(chalk_1.default.cyan("\u2500".repeat(50)));
1231
+ }
1232
+ function printWarnings2(warnings) {
1233
+ if (warnings.length === 0)
1234
+ return;
1235
+ console.log("\n" + chalk_1.default.yellow.bold("Avisos:"));
1236
+ for (const w of warnings) {
1237
+ console.log(chalk_1.default.yellow(` ! ${w}`));
1238
+ }
1239
+ }
1240
+ function printNextSteps2(steps) {
1241
+ if (steps.length === 0)
1242
+ return;
1243
+ console.log("\n" + chalk_1.default.dim("Pr\xF3ximos passos:"));
1244
+ for (const s of steps) {
1245
+ console.log(chalk_1.default.dim(` $ ${s}`));
1246
+ }
1247
+ }
1248
+ function printStreamChunk(chunk) {
1249
+ process.stdout.write(chunk);
1250
+ }
1251
+ }
1252
+ });
1253
+
1254
+ // ../ai/dist/tools/diff-renderer.js
1255
+ var require_diff_renderer = __commonJS({
1256
+ "../ai/dist/tools/diff-renderer.js"(exports2) {
1257
+ "use strict";
1258
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
1259
+ if (k2 === void 0) k2 = k;
1260
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1261
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1262
+ desc = { enumerable: true, get: function() {
1263
+ return m[k];
1264
+ } };
1265
+ }
1266
+ Object.defineProperty(o, k2, desc);
1267
+ }) : (function(o, m, k, k2) {
1268
+ if (k2 === void 0) k2 = k;
1269
+ o[k2] = m[k];
1270
+ }));
1271
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
1272
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1273
+ }) : function(o, v) {
1274
+ o["default"] = v;
1275
+ });
1276
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
1277
+ var ownKeys = function(o) {
1278
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1279
+ var ar = [];
1280
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1281
+ return ar;
1282
+ };
1283
+ return ownKeys(o);
1284
+ };
1285
+ return function(mod) {
1286
+ if (mod && mod.__esModule) return mod;
1287
+ var result = {};
1288
+ if (mod != null) {
1289
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1290
+ }
1291
+ __setModuleDefault(result, mod);
1292
+ return result;
1293
+ };
1294
+ })();
1295
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
1296
+ return mod && mod.__esModule ? mod : { "default": mod };
1297
+ };
1298
+ Object.defineProperty(exports2, "__esModule", { value: true });
1299
+ exports2.renderAndConfirm = renderAndConfirm;
1300
+ var chalk_1 = __importDefault(require("chalk"));
1301
+ var DiffLib = __importStar(require("diff"));
1302
+ async function renderAndConfirm(diffs, ask) {
1303
+ console.log("");
1304
+ for (const file of diffs) {
1305
+ const isNew = file.oldContent === null;
1306
+ const label = isNew ? ` ${chalk_1.default.bold(file.path)} ${chalk_1.default.blue("[novo]")}` : ` ${chalk_1.default.bold(file.path)} ${chalk_1.default.yellow("[modificado]")}`;
1307
+ console.log("\n" + label);
1308
+ console.log(chalk_1.default.dim("\u2500".repeat(62)));
1309
+ if (isNew) {
1310
+ for (const line of file.newContent.split("\n")) {
1311
+ console.log(chalk_1.default.green(`+ ${line}`));
1312
+ }
1313
+ } else {
1314
+ const changes = DiffLib.diffLines(file.oldContent, file.newContent);
1315
+ for (const change of changes) {
1316
+ const lines = change.value.split("\n");
1317
+ if (lines[lines.length - 1] === "")
1318
+ lines.pop();
1319
+ for (const line of lines) {
1320
+ if (change.added) {
1321
+ console.log(chalk_1.default.green(`+ ${line}`));
1322
+ } else if (change.removed) {
1323
+ console.log(chalk_1.default.red(`- ${line}`));
1324
+ } else {
1325
+ console.log(` ${line}`);
1326
+ }
1327
+ }
1328
+ }
1329
+ }
1330
+ console.log(chalk_1.default.dim("\u2500".repeat(62)));
1331
+ }
1332
+ const newCount = diffs.filter((d) => d.oldContent === null).length;
1333
+ const modCount = diffs.filter((d) => d.oldContent !== null).length;
1334
+ const parts = [];
1335
+ if (modCount > 0)
1336
+ parts.push(`${modCount} modificado(s)`);
1337
+ if (newCount > 0)
1338
+ parts.push(`${newCount} novo(s)`);
1339
+ console.log(chalk_1.default.dim("\n " + parts.join(" \xB7 ") + "\n"));
1340
+ const answer = await ask("Aplicar mudan\xE7as? [y/n] ");
1341
+ return answer.toLowerCase() === "y";
1342
+ }
1343
+ }
1344
+ });
1345
+
1346
+ // ../ai/dist/tools/safe-path.js
1347
+ var require_safe_path = __commonJS({
1348
+ "../ai/dist/tools/safe-path.js"(exports2) {
1349
+ "use strict";
1350
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
1351
+ if (k2 === void 0) k2 = k;
1352
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1353
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1354
+ desc = { enumerable: true, get: function() {
1355
+ return m[k];
1356
+ } };
1357
+ }
1358
+ Object.defineProperty(o, k2, desc);
1359
+ }) : (function(o, m, k, k2) {
1360
+ if (k2 === void 0) k2 = k;
1361
+ o[k2] = m[k];
1362
+ }));
1363
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
1364
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1365
+ }) : function(o, v) {
1366
+ o["default"] = v;
1367
+ });
1368
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
1369
+ var ownKeys = function(o) {
1370
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1371
+ var ar = [];
1372
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1373
+ return ar;
1374
+ };
1375
+ return ownKeys(o);
1376
+ };
1377
+ return function(mod) {
1378
+ if (mod && mod.__esModule) return mod;
1379
+ var result = {};
1380
+ if (mod != null) {
1381
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1382
+ }
1383
+ __setModuleDefault(result, mod);
1384
+ return result;
1385
+ };
1386
+ })();
1387
+ Object.defineProperty(exports2, "__esModule", { value: true });
1388
+ exports2.NATIVE_PROVIDERS = void 0;
1389
+ exports2.safeJoin = safeJoin;
1390
+ exports2.isWithin = isWithin;
1391
+ exports2.errMessage = errMessage;
1392
+ exports2.assertValidStackName = assertValidStackName;
1393
+ exports2.assertValidProvider = assertValidProvider;
1394
+ var path2 = __importStar(require("path"));
1395
+ exports2.NATIVE_PROVIDERS = ["aws", "azure", "gcp", "terraform"];
1396
+ var STACK_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
1397
+ var PROVIDER_PATTERN = /^[a-z0-9_-]+$/;
1398
+ function safeJoin(baseDir, relativePath) {
1399
+ if (typeof relativePath !== "string" || relativePath.length === 0) {
1400
+ throw new Error("Caminho vazio ou inv\xE1lido recebido.");
1401
+ }
1402
+ if (path2.isAbsolute(relativePath)) {
1403
+ throw new Error(`Caminho absoluto rejeitado por seguran\xE7a: "${relativePath}". Use sempre caminhos relativos ao projeto.`);
1404
+ }
1405
+ const baseResolved = path2.resolve(baseDir);
1406
+ const fullResolved = path2.resolve(baseResolved, relativePath);
1407
+ if (fullResolved !== baseResolved && !fullResolved.startsWith(baseResolved + path2.sep)) {
1408
+ throw new Error(`Caminho fora do diret\xF3rio do projeto rejeitado: "${relativePath}" (resolveria para "${fullResolved}"). Path traversal n\xE3o \xE9 permitido.`);
1409
+ }
1410
+ return fullResolved;
1411
+ }
1412
+ function isWithin(baseDir, candidatePath) {
1413
+ try {
1414
+ const baseResolved = path2.resolve(baseDir);
1415
+ const fullResolved = path2.isAbsolute(candidatePath) ? path2.resolve(candidatePath) : path2.resolve(baseResolved, candidatePath);
1416
+ return fullResolved === baseResolved || fullResolved.startsWith(baseResolved + path2.sep);
1417
+ } catch {
1418
+ return false;
1419
+ }
1420
+ }
1421
+ function errMessage(err) {
1422
+ if (err instanceof Error)
1423
+ return err.message;
1424
+ if (typeof err === "string")
1425
+ return err;
1426
+ if (err === null)
1427
+ return "null";
1428
+ if (err === void 0)
1429
+ return "undefined";
1430
+ if (typeof err === "object" && "message" in err) {
1431
+ const m = err.message;
1432
+ if (typeof m === "string")
1433
+ return m;
1434
+ }
1435
+ try {
1436
+ const s = JSON.stringify(err);
1437
+ return typeof s === "string" ? s : String(err);
1438
+ } catch {
1439
+ return String(err);
1440
+ }
1441
+ }
1442
+ function assertValidStackName(stackName) {
1443
+ if (typeof stackName !== "string" || !STACK_NAME_PATTERN.test(stackName)) {
1444
+ throw new Error(`Nome de stack inv\xE1lido: "${stackName}". Use apenas letras, n\xFAmeros, h\xEDfen e underscore (regex: /^[A-Za-z0-9_-]+$/).`);
1445
+ }
1446
+ }
1447
+ function assertValidProvider(provider, allowlist) {
1448
+ if (typeof provider !== "string" || !PROVIDER_PATTERN.test(provider)) {
1449
+ throw new Error(`Nome de provider inv\xE1lido: "${provider}". Use apenas letras min\xFAsculas, n\xFAmeros, h\xEDfen e underscore.`);
1450
+ }
1451
+ const allowed = allowlist ?? exports2.NATIVE_PROVIDERS;
1452
+ if (!allowed.includes(provider)) {
1453
+ throw new Error(`Provider "${provider}" n\xE3o permitido. Allowlist: ${allowed.join(", ")}.`);
1454
+ }
1455
+ }
1456
+ }
1457
+ });
1458
+
1459
+ // ../ai/dist/tools/file-writer.js
1460
+ var require_file_writer = __commonJS({
1461
+ "../ai/dist/tools/file-writer.js"(exports2) {
1462
+ "use strict";
1463
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
1464
+ if (k2 === void 0) k2 = k;
1465
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1466
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1467
+ desc = { enumerable: true, get: function() {
1468
+ return m[k];
1469
+ } };
1470
+ }
1471
+ Object.defineProperty(o, k2, desc);
1472
+ }) : (function(o, m, k, k2) {
1473
+ if (k2 === void 0) k2 = k;
1474
+ o[k2] = m[k];
1475
+ }));
1476
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
1477
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1478
+ }) : function(o, v) {
1479
+ o["default"] = v;
1480
+ });
1481
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
1482
+ var ownKeys = function(o) {
1483
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1484
+ var ar = [];
1485
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1486
+ return ar;
1487
+ };
1488
+ return ownKeys(o);
1489
+ };
1490
+ return function(mod) {
1491
+ if (mod && mod.__esModule) return mod;
1492
+ var result = {};
1493
+ if (mod != null) {
1494
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1495
+ }
1496
+ __setModuleDefault(result, mod);
1497
+ return result;
1498
+ };
1499
+ })();
1500
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
1501
+ return mod && mod.__esModule ? mod : { "default": mod };
1502
+ };
1503
+ Object.defineProperty(exports2, "__esModule", { value: true });
1504
+ exports2.writeGeneratedFiles = writeGeneratedFiles2;
1505
+ var fs2 = __importStar(require("fs"));
1506
+ var path2 = __importStar(require("path"));
1507
+ var chalk_1 = __importDefault(require("chalk"));
1508
+ var diff_renderer_1 = require_diff_renderer();
1509
+ var safe_path_1 = require_safe_path();
1510
+ async function writeGeneratedFiles2(files, projectDir, dryRun, ask) {
1511
+ const validated = [];
1512
+ for (const file of files) {
1513
+ const fullPath = (0, safe_path_1.safeJoin)(projectDir, file.path);
1514
+ validated.push({ file, fullPath });
1515
+ }
1516
+ if (dryRun) {
1517
+ console.log(chalk_1.default.dim("\n[dry-run] Arquivos que seriam gerados:\n"));
1518
+ for (const { file } of validated) {
1519
+ console.log(chalk_1.default.cyan(` ${file.path}`));
1520
+ console.log(chalk_1.default.dim("\u2500".repeat(62)));
1521
+ for (const line of file.content.split("\n")) {
1522
+ console.log(chalk_1.default.green(`+ ${line}`));
1523
+ }
1524
+ console.log(chalk_1.default.dim("\u2500".repeat(62)));
1525
+ console.log("");
1526
+ }
1527
+ console.log(chalk_1.default.dim("[dry-run] Nenhum arquivo foi salvo.\n"));
1528
+ return;
1529
+ }
1530
+ const diffs = validated.map(({ file, fullPath }) => {
1531
+ let oldContent = null;
1532
+ try {
1533
+ oldContent = fs2.readFileSync(fullPath, "utf-8");
1534
+ } catch {
1535
+ }
1536
+ return { path: file.path, oldContent, newContent: file.content };
1537
+ });
1538
+ const confirmed = await (0, diff_renderer_1.renderAndConfirm)(diffs, ask);
1539
+ if (!confirmed) {
1540
+ console.log(chalk_1.default.dim("\n Opera\xE7\xE3o cancelada. Nenhum arquivo foi alterado.\n"));
1541
+ return;
1542
+ }
1543
+ for (const { file, fullPath } of validated) {
1544
+ fs2.mkdirSync(path2.dirname(fullPath), { recursive: true });
1545
+ fs2.writeFileSync(fullPath, file.content, "utf-8");
1546
+ console.log(chalk_1.default.green(` \u2713 ${file.path}`));
1547
+ }
1548
+ console.log("");
1549
+ }
1550
+ }
1551
+ });
1552
+
1553
+ // ../ai/dist/tools/file-deleter.js
1554
+ var require_file_deleter = __commonJS({
1555
+ "../ai/dist/tools/file-deleter.js"(exports2) {
1556
+ "use strict";
1557
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
1558
+ if (k2 === void 0) k2 = k;
1559
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1560
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1561
+ desc = { enumerable: true, get: function() {
1562
+ return m[k];
1563
+ } };
1564
+ }
1565
+ Object.defineProperty(o, k2, desc);
1566
+ }) : (function(o, m, k, k2) {
1567
+ if (k2 === void 0) k2 = k;
1568
+ o[k2] = m[k];
1569
+ }));
1570
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
1571
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1572
+ }) : function(o, v) {
1573
+ o["default"] = v;
1574
+ });
1575
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
1576
+ var ownKeys = function(o) {
1577
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1578
+ var ar = [];
1579
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1580
+ return ar;
1581
+ };
1582
+ return ownKeys(o);
1583
+ };
1584
+ return function(mod) {
1585
+ if (mod && mod.__esModule) return mod;
1586
+ var result = {};
1587
+ if (mod != null) {
1588
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1589
+ }
1590
+ __setModuleDefault(result, mod);
1591
+ return result;
1592
+ };
1593
+ })();
1594
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
1595
+ return mod && mod.__esModule ? mod : { "default": mod };
1596
+ };
1597
+ Object.defineProperty(exports2, "__esModule", { value: true });
1598
+ exports2.deleteFiles = deleteFiles;
1599
+ var fs2 = __importStar(require("fs"));
1600
+ var path2 = __importStar(require("path"));
1601
+ var cp2 = __importStar(require("child_process"));
1602
+ var chalk_1 = __importDefault(require("chalk"));
1603
+ var safe_path_1 = require_safe_path();
1604
+ function synthOutPaths(filePath, projectDir) {
1605
+ const basename = path2.basename(filePath).replace(/\.(ts|js)$/, "");
1606
+ const root = path2.join(projectDir, "synth-out");
1607
+ if (!fs2.existsSync(root))
1608
+ return [];
1609
+ const found = [];
1610
+ const check = (dir) => {
1611
+ for (const ext of [".json", ".tf"]) {
1612
+ const c = path2.join(dir, `${basename}${ext}`);
1613
+ if (fs2.existsSync(c) && fs2.statSync(c).isFile())
1614
+ found.push(c);
1615
+ }
1616
+ };
1617
+ check(root);
1618
+ try {
1619
+ for (const entry of fs2.readdirSync(root, { withFileTypes: true })) {
1620
+ if (entry.isDirectory())
1621
+ check(path2.join(root, entry.name));
1622
+ }
1623
+ } catch {
1624
+ }
1625
+ return found;
1626
+ }
1627
+ function escapeRegex(s) {
1628
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1629
+ }
1630
+ function removeReferences(stackName, projectDir) {
1631
+ const modified = [];
1632
+ const stacksDir = path2.join(projectDir, "stacks");
1633
+ if (!fs2.existsSync(stacksDir))
1634
+ return modified;
1635
+ const escaped = escapeRegex(stackName);
1636
+ const findTs = (dir) => {
1637
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
1638
+ const files = [];
1639
+ for (const e of entries) {
1640
+ const full = path2.join(dir, e.name);
1641
+ if (e.isDirectory())
1642
+ files.push(...findTs(full));
1643
+ else if (e.name.endsWith(".ts"))
1644
+ files.push(full);
1645
+ }
1646
+ return files;
1647
+ };
1648
+ for (const file of findTs(stacksDir)) {
1649
+ const content = fs2.readFileSync(file, "utf-8");
1650
+ const pattern = new RegExp(`(import[^;]*from\\s*['"][^'"]*${escaped}[^'"]*['"]\\s*;?\\n?)|(.*${escaped}.*)`, "g");
1651
+ if (pattern.test(content)) {
1652
+ const cleaned = content.replace(pattern, "").replace(/\n{3,}/g, "\n\n").trim() + "\n";
1653
+ if (cleaned !== content) {
1654
+ fs2.writeFileSync(file, cleaned, "utf-8");
1655
+ modified.push(path2.relative(projectDir, file));
1656
+ }
1657
+ }
1658
+ }
1659
+ return modified;
1660
+ }
1661
+ function resolveCliEntrypoint() {
1662
+ try {
1663
+ return require.resolve("iacmp/bin/run.js");
1664
+ } catch {
1665
+ return null;
1666
+ }
1667
+ }
1668
+ async function deleteFiles(deletions, projectDir, iacProvider, ask, options) {
1669
+ (0, safe_path_1.assertValidProvider)(iacProvider, options?.providerAllowlist);
1670
+ const stackFiles = deletions.filter((f) => f.match(/\.(ts|js)$/) && f.includes("stacks/"));
1671
+ const otherFiles = deletions.filter((f) => !stackFiles.includes(f));
1672
+ const seen = /* @__PURE__ */ new Set();
1673
+ const allToDelete = [];
1674
+ const synthOuts = [];
1675
+ const add = (rel, full) => {
1676
+ if (!seen.has(full)) {
1677
+ seen.add(full);
1678
+ allToDelete.push({ rel, full });
1679
+ }
1680
+ };
1681
+ for (const filePath of stackFiles) {
1682
+ let full;
1683
+ try {
1684
+ full = (0, safe_path_1.safeJoin)(projectDir, filePath);
1685
+ } catch (err) {
1686
+ console.log(chalk_1.default.yellow(` ! ${(0, safe_path_1.errMessage)(err)} \u2014 ignorando ${filePath}`));
1687
+ continue;
1688
+ }
1689
+ if (fs2.existsSync(full))
1690
+ add(filePath, full);
1691
+ for (const synthOut of synthOutPaths(filePath, projectDir)) {
1692
+ const rel = path2.relative(projectDir, synthOut);
1693
+ add(rel, synthOut);
1694
+ if (!synthOuts.includes(rel))
1695
+ synthOuts.push(rel);
1696
+ }
1697
+ }
1698
+ for (const filePath of otherFiles) {
1699
+ let full;
1700
+ try {
1701
+ full = (0, safe_path_1.safeJoin)(projectDir, filePath);
1702
+ } catch (err) {
1703
+ console.log(chalk_1.default.yellow(` ! ${(0, safe_path_1.errMessage)(err)} \u2014 ignorando ${filePath}`));
1704
+ continue;
1705
+ }
1706
+ if (fs2.existsSync(full))
1707
+ add(filePath, full);
1708
+ }
1709
+ if (allToDelete.length === 0) {
1710
+ console.log(chalk_1.default.dim("\n Nenhum arquivo encontrado para remover.\n"));
1711
+ return;
1712
+ }
1713
+ console.log("");
1714
+ console.log(chalk_1.default.red.bold(" Arquivos que ser\xE3o removidos:"));
1715
+ for (const f of allToDelete) {
1716
+ console.log(chalk_1.default.red(` - ${f.rel}`));
1717
+ }
1718
+ console.log("");
1719
+ if (synthOuts.length > 0) {
1720
+ const runDestroy = await ask("Rodar `iacmp destroy` para remover os recursos na nuvem antes de apagar? [y/n] ");
1721
+ if (runDestroy.toLowerCase() === "y") {
1722
+ const cliEntry = resolveCliEntrypoint();
1723
+ for (const synthOut of synthOuts) {
1724
+ const stackName = path2.basename(synthOut).replace(/\.(json|tf)$/, "");
1725
+ try {
1726
+ (0, safe_path_1.assertValidStackName)(stackName);
1727
+ } catch (err) {
1728
+ console.log(chalk_1.default.yellow(` ! ${(0, safe_path_1.errMessage)(err)} \u2014 pulando destroy de ${stackName}`));
1729
+ continue;
1730
+ }
1731
+ console.log(chalk_1.default.dim(`
1732
+ Rodando destroy para ${stackName}...`));
1733
+ try {
1734
+ if (cliEntry) {
1735
+ cp2.execFileSync(process.execPath, [cliEntry, "destroy", "--stack", stackName, "--provider", iacProvider, "--force"], { cwd: projectDir, stdio: "inherit" });
1736
+ } else {
1737
+ cp2.execFileSync("npx", ["iacmp", "destroy", "--stack", stackName, "--provider", iacProvider, "--force"], { cwd: projectDir, stdio: "inherit" });
1738
+ }
1739
+ } catch {
1740
+ console.log(chalk_1.default.yellow(` ! destroy falhou para ${stackName} \u2014 continuando com remo\xE7\xE3o local`));
1741
+ }
1742
+ }
1743
+ }
1744
+ }
1745
+ const confirm = await ask("\nApagar arquivos locais? [y/n] ");
1746
+ if (confirm.toLowerCase() !== "y") {
1747
+ console.log(chalk_1.default.dim(" Remo\xE7\xE3o cancelada.\n"));
1748
+ return;
1749
+ }
1750
+ for (const { rel, full } of allToDelete) {
1751
+ try {
1752
+ fs2.rmSync(full, { force: true });
1753
+ console.log(chalk_1.default.red(` \u2717 ${rel}`));
1754
+ } catch {
1755
+ console.log(chalk_1.default.yellow(` ! N\xE3o foi poss\xEDvel remover: ${rel}`));
1756
+ }
1757
+ }
1758
+ for (const filePath of stackFiles) {
1759
+ const stackName = path2.basename(filePath).replace(/\.(ts|js)$/, "");
1760
+ const modified = removeReferences(stackName, projectDir);
1761
+ for (const f of modified) {
1762
+ console.log(chalk_1.default.yellow(` ~ refer\xEAncias removidas em: ${f}`));
1763
+ }
1764
+ }
1765
+ console.log("");
1766
+ }
1767
+ }
1768
+ });
1769
+
1770
+ // ../ai/dist/tools/synth-runner.js
1771
+ var require_synth_runner = __commonJS({
1772
+ "../ai/dist/tools/synth-runner.js"(exports2) {
1773
+ "use strict";
1774
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
1775
+ return mod && mod.__esModule ? mod : { "default": mod };
1776
+ };
1777
+ Object.defineProperty(exports2, "__esModule", { value: true });
1778
+ exports2.runSynth = runSynth2;
1779
+ var child_process_1 = require("child_process");
1780
+ var chalk_1 = __importDefault(require("chalk"));
1781
+ var safe_path_1 = require_safe_path();
1782
+ function runSynth2(projectDir, provider, options) {
1783
+ try {
1784
+ (0, safe_path_1.assertValidProvider)(provider, options?.providerAllowlist);
1785
+ } catch (err) {
1786
+ console.error(chalk_1.default.red("\nProvider inv\xE1lido para synth:"));
1787
+ console.error(chalk_1.default.red((0, safe_path_1.errMessage)(err)));
1788
+ return false;
1789
+ }
1790
+ let cliEntry = null;
1791
+ try {
1792
+ cliEntry = require.resolve("iacmp/bin/run.js");
1793
+ } catch {
1794
+ cliEntry = null;
1795
+ }
1796
+ try {
1797
+ if (cliEntry) {
1798
+ (0, child_process_1.execFileSync)(process.execPath, [cliEntry, "synth", "--provider", provider], { cwd: projectDir, stdio: "inherit" });
1799
+ } else {
1800
+ (0, child_process_1.execFileSync)("npx", ["iacmp", "synth", "--provider", provider], { cwd: projectDir, stdio: "inherit" });
1801
+ }
1802
+ return true;
1803
+ } catch (err) {
1804
+ const error = err;
1805
+ console.error(chalk_1.default.red("\nErro ao executar iacmp synth:"));
1806
+ if (error.stderr) {
1807
+ console.error(chalk_1.default.red(error.stderr.toString()));
1808
+ }
1809
+ return false;
1810
+ }
1811
+ }
1812
+ }
1813
+ });
1814
+
1815
+ // ../ai/dist/rag/chunker.js
1816
+ var require_chunker = __commonJS({
1817
+ "../ai/dist/rag/chunker.js"(exports2) {
1818
+ "use strict";
1819
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
1820
+ if (k2 === void 0) k2 = k;
1821
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1822
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1823
+ desc = { enumerable: true, get: function() {
1824
+ return m[k];
1825
+ } };
1826
+ }
1827
+ Object.defineProperty(o, k2, desc);
1828
+ }) : (function(o, m, k, k2) {
1829
+ if (k2 === void 0) k2 = k;
1830
+ o[k2] = m[k];
1831
+ }));
1832
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
1833
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
1834
+ }) : function(o, v) {
1835
+ o["default"] = v;
1836
+ });
1837
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
1838
+ var ownKeys = function(o) {
1839
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
1840
+ var ar = [];
1841
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
1842
+ return ar;
1843
+ };
1844
+ return ownKeys(o);
1845
+ };
1846
+ return function(mod) {
1847
+ if (mod && mod.__esModule) return mod;
1848
+ var result = {};
1849
+ if (mod != null) {
1850
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
1851
+ }
1852
+ __setModuleDefault(result, mod);
1853
+ return result;
1854
+ };
1855
+ })();
1856
+ Object.defineProperty(exports2, "__esModule", { value: true });
1857
+ exports2.chunkStackFile = chunkStackFile;
1858
+ exports2.chunkIacmpDocs = chunkIacmpDocs;
1859
+ exports2.chunkKnowledgeFile = chunkKnowledgeFile;
1860
+ var fs2 = __importStar(require("fs"));
1861
+ var path2 = __importStar(require("path"));
1862
+ function chunkStackFile(filePath, projectDir) {
1863
+ const content = fs2.readFileSync(filePath, "utf-8");
1864
+ const rel = path2.relative(projectDir, filePath);
1865
+ const stackName = path2.basename(filePath, ".ts");
1866
+ const chunks = [];
1867
+ const constructRegex = /new\s+([\w]+\.[\w]+)\s*\(\s*\w+\s*,\s*'([\w-]+)'\s*,\s*(\{[\s\S]*?\})\s*\)/g;
1868
+ let match;
1869
+ let index = 0;
1870
+ while ((match = constructRegex.exec(content)) !== null) {
1871
+ const constructType = match[1];
1872
+ const constructId = match[2];
1873
+ const propsRaw = match[3];
1874
+ chunks.push({
1875
+ id: `stack:${rel}:${constructId}`,
1876
+ content: `[construct] ${constructType} "${constructId}" em ${rel}
1877
+ ${propsRaw}`,
1878
+ metadata: {
1879
+ source: "project-stack",
1880
+ file: rel,
1881
+ stackName,
1882
+ constructType,
1883
+ constructId
1884
+ }
1885
+ });
1886
+ index++;
1887
+ }
1888
+ if (chunks.length === 0 && content.trim().length > 0) {
1889
+ chunks.push({
1890
+ id: `stack:${rel}:full`,
1891
+ content: `[stack] ${stackName} em ${rel}
1892
+ ${content}`,
1893
+ metadata: {
1894
+ source: "project-stack",
1895
+ file: rel,
1896
+ stackName
1897
+ }
1898
+ });
1899
+ }
1900
+ return chunks;
1901
+ }
1902
+ function chunkIacmpDocs(systemPromptTemplate) {
1903
+ const chunks = [];
1904
+ const sections = systemPromptTemplate.split(/(?=^### )/m);
1905
+ for (const section of sections) {
1906
+ const titleMatch = section.match(/^### (.+)/);
1907
+ if (!titleMatch)
1908
+ continue;
1909
+ const title = titleMatch[1].trim();
1910
+ const trimmed = section.trim();
1911
+ if (trimmed.length < 30)
1912
+ continue;
1913
+ chunks.push({
1914
+ id: `docs:${title.replace(/[^a-zA-Z0-9]/g, "-")}`,
1915
+ content: trimmed,
1916
+ metadata: {
1917
+ source: "iacmp-docs",
1918
+ section: title
1919
+ }
1920
+ });
1921
+ }
1922
+ return chunks;
1923
+ }
1924
+ function chunkKnowledgeFile(filePath, platform) {
1925
+ const content = fs2.readFileSync(filePath, "utf-8");
1926
+ const fileName = path2.basename(filePath, ".md");
1927
+ const chunks = [];
1928
+ const sections = content.split(/(?=^#{1,3} )/m);
1929
+ for (const section of sections) {
1930
+ const titleMatch = section.match(/^#{1,3} (.+)/);
1931
+ const title = titleMatch ? titleMatch[1].trim() : fileName;
1932
+ const trimmed = section.trim();
1933
+ if (trimmed.length < 50)
1934
+ continue;
1935
+ if (trimmed.length > 2e3) {
1936
+ const paragraphs = trimmed.split(/\n\n+/);
1937
+ let buffer = "";
1938
+ let bufferIndex = 0;
1939
+ for (const para of paragraphs) {
1940
+ buffer += para + "\n\n";
1941
+ if (buffer.length > 800) {
1942
+ chunks.push({
1943
+ id: `knowledge:${platform}:${fileName}:${title.replace(/[^a-zA-Z0-9]/g, "-")}-${bufferIndex}`,
1944
+ content: `[${platform.toUpperCase()}] ${title}
1945
+
1946
+ ${buffer.trim()}`,
1947
+ metadata: {
1948
+ source: "platform-knowledge",
1949
+ platform,
1950
+ file: path2.basename(filePath),
1951
+ section: title
1952
+ }
1953
+ });
1954
+ buffer = "";
1955
+ bufferIndex++;
1956
+ }
1957
+ }
1958
+ if (buffer.trim().length > 50) {
1959
+ chunks.push({
1960
+ id: `knowledge:${platform}:${fileName}:${title.replace(/[^a-zA-Z0-9]/g, "-")}-${bufferIndex}`,
1961
+ content: `[${platform.toUpperCase()}] ${title}
1962
+
1963
+ ${buffer.trim()}`,
1964
+ metadata: {
1965
+ source: "platform-knowledge",
1966
+ platform,
1967
+ file: path2.basename(filePath),
1968
+ section: title
1969
+ }
1970
+ });
1971
+ }
1972
+ } else {
1973
+ chunks.push({
1974
+ id: `knowledge:${platform}:${fileName}:${title.replace(/[^a-zA-Z0-9]/g, "-")}`,
1975
+ content: `[${platform.toUpperCase()}] ${title}
1976
+
1977
+ ${trimmed}`,
1978
+ metadata: {
1979
+ source: "platform-knowledge",
1980
+ platform,
1981
+ file: path2.basename(filePath),
1982
+ section: title
1983
+ }
1984
+ });
1985
+ }
1986
+ }
1987
+ return chunks;
1988
+ }
1989
+ }
1990
+ });
1991
+
1992
+ // ../ai/dist/rag/contextualizer.js
1993
+ var require_contextualizer = __commonJS({
1994
+ "../ai/dist/rag/contextualizer.js"(exports2) {
1995
+ "use strict";
1996
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
1997
+ return mod && mod.__esModule ? mod : { "default": mod };
1998
+ };
1999
+ Object.defineProperty(exports2, "__esModule", { value: true });
2000
+ exports2.Contextualizer = void 0;
2001
+ var sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
2002
+ var CONTEXTUALIZER_PROMPT = `Voc\xEA est\xE1 processando um chunk de documento para indexa\xE7\xE3o em um sistema RAG de infraestrutura como c\xF3digo.
2003
+
2004
+ Dado o documento completo e o chunk espec\xEDfico abaixo, gere um par\xE1grafo conciso (2-4 frases) que:
2005
+ 1. Explique o que este chunk representa no contexto do documento maior
2006
+ 2. Mencione conceitos-chave, servi\xE7os cloud, ou padr\xF5es de arquitetura relevantes
2007
+ 3. Inclua termos alternativos ou sin\xF4nimos que ajudem na busca (ex: "Lambda" e "fun\xE7\xE3o serverless", "RDS" e "banco relacional")
2008
+
2009
+ Seja direto e t\xE9cnico. N\xE3o use markdown. Responda apenas com o par\xE1grafo de contexto.
2010
+
2011
+ <documento_completo>
2012
+ {DOCUMENT}
2013
+ </documento_completo>
2014
+
2015
+ <chunk>
2016
+ {CHUNK}
2017
+ </chunk>`;
2018
+ var Contextualizer = class {
2019
+ client;
2020
+ model = "claude-haiku-4-5";
2021
+ // usa Haiku para minimizar custo — tarefa simples
2022
+ constructor(apiKey) {
2023
+ this.client = new sdk_1.default({ apiKey });
2024
+ }
2025
+ // Enriquece um único chunk com contexto gerado pelo Claude
2026
+ async enrichChunk(chunk, fullDocument) {
2027
+ const prompt = CONTEXTUALIZER_PROMPT.replace("{DOCUMENT}", fullDocument.slice(0, 8e3)).replace("{CHUNK}", chunk.content.slice(0, 2e3));
2028
+ try {
2029
+ const response = await this.client.messages.create({
2030
+ model: this.model,
2031
+ max_tokens: 256,
2032
+ messages: [{ role: "user", content: prompt }]
2033
+ });
2034
+ const contextText = response.content[0].type === "text" ? response.content[0].text.trim() : "";
2035
+ return {
2036
+ ...chunk,
2037
+ // contextualContent = contexto gerado + conteúdo original
2038
+ // É isso que vai para o índice BM25/vetorial
2039
+ contextualContent: `${contextText}
2040
+
2041
+ ${chunk.content}`
2042
+ };
2043
+ } catch {
2044
+ return { ...chunk, contextualContent: chunk.content };
2045
+ }
2046
+ }
2047
+ // Enriquece um lote de chunks em paralelo com controle de concorrência
2048
+ async enrichBatch(chunks, fullDocument, options = {}) {
2049
+ const { concurrency = 5, onProgress } = options;
2050
+ const results = new Array(chunks.length);
2051
+ let done = 0;
2052
+ for (let i = 0; i < chunks.length; i += concurrency) {
2053
+ const batch = chunks.slice(i, i + concurrency);
2054
+ const batchResults = await Promise.all(batch.map((chunk) => this.enrichChunk(chunk, fullDocument)));
2055
+ for (let j = 0; j < batchResults.length; j++) {
2056
+ results[i + j] = batchResults[j];
2057
+ }
2058
+ done += batch.length;
2059
+ onProgress?.(done, chunks.length);
2060
+ }
2061
+ return results;
2062
+ }
2063
+ };
2064
+ exports2.Contextualizer = Contextualizer;
2065
+ }
2066
+ });
2067
+
2068
+ // ../ai/dist/rag/bm25.js
2069
+ var require_bm25 = __commonJS({
2070
+ "../ai/dist/rag/bm25.js"(exports2) {
2071
+ "use strict";
2072
+ Object.defineProperty(exports2, "__esModule", { value: true });
2073
+ exports2.buildBM25Index = buildBM25Index;
2074
+ exports2.bm25Search = bm25Search;
2075
+ var K1 = 1.5;
2076
+ var B = 0.75;
2077
+ function tokenize(text) {
2078
+ return text.toLowerCase().replace(/[^a-z0-9\s._-]/g, " ").split(/\s+/).filter((t) => t.length > 1);
2079
+ }
2080
+ function termFrequency(tokens) {
2081
+ const tf = {};
2082
+ for (const t of tokens) {
2083
+ tf[t] = (tf[t] ?? 0) + 1;
2084
+ }
2085
+ return tf;
2086
+ }
2087
+ function buildBM25Index(chunks) {
2088
+ const documents = [];
2089
+ const df = {};
2090
+ let totalLength = 0;
2091
+ for (const chunk of chunks) {
2092
+ const text = chunk.contextualContent ?? chunk.content;
2093
+ const tokens = tokenize(text);
2094
+ const terms = termFrequency(tokens);
2095
+ totalLength += tokens.length;
2096
+ documents.push({ id: chunk.id, terms, length: tokens.length });
2097
+ for (const term of Object.keys(terms)) {
2098
+ df[term] = (df[term] ?? 0) + 1;
2099
+ }
2100
+ }
2101
+ return {
2102
+ documents,
2103
+ df,
2104
+ avgLength: documents.length > 0 ? totalLength / documents.length : 0,
2105
+ totalDocs: documents.length
2106
+ };
2107
+ }
2108
+ function bm25Search(index, query, topK = 5) {
2109
+ const queryTerms = tokenize(query);
2110
+ const scores = {};
2111
+ for (const term of queryTerms) {
2112
+ const docFreq = index.df[term] ?? 0;
2113
+ if (docFreq === 0)
2114
+ continue;
2115
+ const idf = Math.log((index.totalDocs - docFreq + 0.5) / (docFreq + 0.5) + 1);
2116
+ for (const doc of index.documents) {
2117
+ const tf = doc.terms[term] ?? 0;
2118
+ if (tf === 0)
2119
+ continue;
2120
+ const tfNorm = tf * (K1 + 1) / (tf + K1 * (1 - B + B * (doc.length / index.avgLength)));
2121
+ scores[doc.id] = (scores[doc.id] ?? 0) + idf * tfNorm;
2122
+ }
2123
+ }
2124
+ return Object.entries(scores).sort((a, b) => b[1] - a[1]).slice(0, topK).map(([id, score]) => ({ id, score }));
2125
+ }
2126
+ }
2127
+ });
2128
+
2129
+ // ../ai/dist/rag/embedder.js
2130
+ var require_embedder = __commonJS({
2131
+ "../ai/dist/rag/embedder.js"(exports2) {
2132
+ "use strict";
2133
+ Object.defineProperty(exports2, "__esModule", { value: true });
2134
+ exports2.BM25Embedder = exports2.VoyageEmbedder = void 0;
2135
+ exports2.createEmbedder = createEmbedder;
2136
+ var VoyageEmbedder = class {
2137
+ apiKey;
2138
+ model = "voyage-code-2";
2139
+ endpoint = "https://api.voyageai.com/v1/embeddings";
2140
+ constructor(apiKey) {
2141
+ this.apiKey = apiKey;
2142
+ }
2143
+ async embed(texts) {
2144
+ if (texts.length === 0)
2145
+ return [];
2146
+ const BATCH_SIZE = 128;
2147
+ const results = [];
2148
+ for (let i = 0; i < texts.length; i += BATCH_SIZE) {
2149
+ const batch = texts.slice(i, i + BATCH_SIZE);
2150
+ const batchVectors = await this.embedBatch(batch);
2151
+ results.push(...batchVectors);
2152
+ }
2153
+ return results;
2154
+ }
2155
+ async embedBatch(texts) {
2156
+ const controller = new AbortController();
2157
+ const timeout = setTimeout(() => controller.abort(), 3e4);
2158
+ try {
2159
+ const response = await fetch(this.endpoint, {
2160
+ method: "POST",
2161
+ headers: {
2162
+ "Authorization": `Bearer ${this.apiKey}`,
2163
+ "Content-Type": "application/json"
2164
+ },
2165
+ body: JSON.stringify({
2166
+ model: this.model,
2167
+ input: texts,
2168
+ input_type: "document"
2169
+ }),
2170
+ signal: controller.signal
2171
+ });
2172
+ if (!response.ok) {
2173
+ const body = await response.text();
2174
+ throw new Error(`Voyage API error ${response.status}: ${body}`);
2175
+ }
2176
+ const data = await response.json();
2177
+ const sorted = data.data.sort((a, b) => a.index - b.index);
2178
+ return sorted.map((d) => d.embedding);
2179
+ } finally {
2180
+ clearTimeout(timeout);
2181
+ }
2182
+ }
2183
+ };
2184
+ exports2.VoyageEmbedder = VoyageEmbedder;
2185
+ var BM25Embedder = class {
2186
+ vocabSize;
2187
+ constructor(vocabSize = 4096) {
2188
+ this.vocabSize = vocabSize;
2189
+ }
2190
+ async embed(texts) {
2191
+ return texts.map((text) => this.textToVector(text));
2192
+ }
2193
+ textToVector(text) {
2194
+ const tokens = this.tokenize(text);
2195
+ const tf = this.termFrequency(tokens);
2196
+ const vector = new Float64Array(this.vocabSize);
2197
+ for (const [term, freq] of Object.entries(tf)) {
2198
+ const hash = this.termHash(term);
2199
+ const pos = Math.abs(hash) % this.vocabSize;
2200
+ vector[pos] += Math.log(1 + freq) / Math.max(1, tokens.length);
2201
+ }
2202
+ return this.normalizeL2(Array.from(vector));
2203
+ }
2204
+ tokenize(text) {
2205
+ return text.toLowerCase().replace(/[^a-z0-9\s._-]/g, " ").split(/\s+/).filter((t) => t.length > 1);
2206
+ }
2207
+ termFrequency(tokens) {
2208
+ const tf = {};
2209
+ for (const t of tokens) {
2210
+ tf[t] = (tf[t] ?? 0) + 1;
2211
+ }
2212
+ return tf;
2213
+ }
2214
+ termHash(term) {
2215
+ let hash = 5381;
2216
+ for (let i = 0; i < term.length; i++) {
2217
+ hash = (hash << 5) + hash ^ term.charCodeAt(i);
2218
+ hash = hash & 2147483647;
2219
+ }
2220
+ return hash;
2221
+ }
2222
+ normalizeL2(vector) {
2223
+ const norm = Math.sqrt(vector.reduce((sum, v) => sum + v * v, 0));
2224
+ if (norm === 0)
2225
+ return vector;
2226
+ return vector.map((v) => v / norm);
2227
+ }
2228
+ };
2229
+ exports2.BM25Embedder = BM25Embedder;
2230
+ function createEmbedder(voyageApiKey) {
2231
+ if (voyageApiKey) {
2232
+ return new VoyageEmbedder(voyageApiKey);
2233
+ }
2234
+ return new BM25Embedder();
2235
+ }
2236
+ }
2237
+ });
2238
+
2239
+ // ../ai/dist/rag/vector-store.js
2240
+ var require_vector_store = __commonJS({
2241
+ "../ai/dist/rag/vector-store.js"(exports2) {
2242
+ "use strict";
2243
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
2244
+ if (k2 === void 0) k2 = k;
2245
+ var desc = Object.getOwnPropertyDescriptor(m, k);
2246
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
2247
+ desc = { enumerable: true, get: function() {
2248
+ return m[k];
2249
+ } };
2250
+ }
2251
+ Object.defineProperty(o, k2, desc);
2252
+ }) : (function(o, m, k, k2) {
2253
+ if (k2 === void 0) k2 = k;
2254
+ o[k2] = m[k];
2255
+ }));
2256
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
2257
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
2258
+ }) : function(o, v) {
2259
+ o["default"] = v;
2260
+ });
2261
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
2262
+ var ownKeys = function(o) {
2263
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
2264
+ var ar = [];
2265
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
2266
+ return ar;
2267
+ };
2268
+ return ownKeys(o);
2269
+ };
2270
+ return function(mod) {
2271
+ if (mod && mod.__esModule) return mod;
2272
+ var result = {};
2273
+ if (mod != null) {
2274
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
2275
+ }
2276
+ __setModuleDefault(result, mod);
2277
+ return result;
2278
+ };
2279
+ })();
2280
+ Object.defineProperty(exports2, "__esModule", { value: true });
2281
+ exports2.VectorStore = void 0;
2282
+ var fs2 = __importStar(require("fs"));
2283
+ var path2 = __importStar(require("path"));
2284
+ var VectorStore = class {
2285
+ entries = [];
2286
+ dimension = 0;
2287
+ add(id, vector, metadata) {
2288
+ if (this.dimension === 0) {
2289
+ this.dimension = vector.length;
2290
+ }
2291
+ const normalized = this.normalizeL2(vector);
2292
+ this.entries.push({
2293
+ id,
2294
+ vector: new Float32Array(normalized),
2295
+ metadata
2296
+ });
2297
+ }
2298
+ search(queryVector, topK = 5) {
2299
+ if (this.entries.length === 0)
2300
+ return [];
2301
+ const normalizedQuery = new Float32Array(this.normalizeL2(queryVector));
2302
+ const scores = [];
2303
+ for (let i = 0; i < this.entries.length; i++) {
2304
+ const score = this.cosineSimilarity(normalizedQuery, this.entries[i].vector);
2305
+ scores.push({ index: i, score });
2306
+ }
2307
+ return scores.sort((a, b) => b.score - a.score).slice(0, topK).map(({ index, score }) => ({
2308
+ id: this.entries[index].id,
2309
+ score,
2310
+ metadata: this.entries[index].metadata
2311
+ }));
2312
+ }
2313
+ size() {
2314
+ return this.entries.length;
2315
+ }
2316
+ clear() {
2317
+ this.entries = [];
2318
+ this.dimension = 0;
2319
+ }
2320
+ // Serializa o índice em binário para persistência
2321
+ // Formato: [header: 16 bytes][entries...]
2322
+ // Header: magic(4) + version(4) + numEntries(4) + dimension(4)
2323
+ // Entry: idLen(4) + id(idLen) + metadataLen(4) + metadata(metadataLen) + vector(dimension * 4)
2324
+ save(filePath) {
2325
+ fs2.mkdirSync(path2.dirname(filePath), { recursive: true });
2326
+ const MAGIC = 1447379796;
2327
+ const VERSION = 1;
2328
+ const encodedEntries = this.entries.map((entry) => {
2329
+ const idBytes = Buffer.from(entry.id, "utf-8");
2330
+ const metaBytes = Buffer.from(JSON.stringify(entry.metadata), "utf-8");
2331
+ return { entry, idBytes, metaBytes };
2332
+ });
2333
+ const totalSize = 16 + encodedEntries.reduce((sum, { entry, idBytes, metaBytes }) => {
2334
+ return sum + 4 + idBytes.length + 4 + metaBytes.length + entry.vector.length * 4;
2335
+ }, 0);
2336
+ const buffer = Buffer.alloc(totalSize);
2337
+ let offset = 0;
2338
+ buffer.writeUInt32BE(MAGIC, offset);
2339
+ offset += 4;
2340
+ buffer.writeUInt32BE(VERSION, offset);
2341
+ offset += 4;
2342
+ buffer.writeUInt32BE(this.entries.length, offset);
2343
+ offset += 4;
2344
+ buffer.writeUInt32BE(this.dimension, offset);
2345
+ offset += 4;
2346
+ for (const { entry, idBytes, metaBytes } of encodedEntries) {
2347
+ buffer.writeUInt32BE(idBytes.length, offset);
2348
+ offset += 4;
2349
+ idBytes.copy(buffer, offset);
2350
+ offset += idBytes.length;
2351
+ buffer.writeUInt32BE(metaBytes.length, offset);
2352
+ offset += 4;
2353
+ metaBytes.copy(buffer, offset);
2354
+ offset += metaBytes.length;
2355
+ for (const v of entry.vector) {
2356
+ buffer.writeFloatBE(v, offset);
2357
+ offset += 4;
2358
+ }
2359
+ }
2360
+ fs2.writeFileSync(filePath, buffer);
2361
+ }
2362
+ // Carrega índice do binário
2363
+ load(filePath) {
2364
+ if (!fs2.existsSync(filePath))
2365
+ return false;
2366
+ try {
2367
+ const buffer = fs2.readFileSync(filePath);
2368
+ let offset = 0;
2369
+ const magic = buffer.readUInt32BE(offset);
2370
+ offset += 4;
2371
+ if (magic !== 1447379796)
2372
+ return false;
2373
+ const version = buffer.readUInt32BE(offset);
2374
+ offset += 4;
2375
+ if (version !== 1)
2376
+ return false;
2377
+ const numEntries = buffer.readUInt32BE(offset);
2378
+ offset += 4;
2379
+ const dimension = buffer.readUInt32BE(offset);
2380
+ offset += 4;
2381
+ this.dimension = dimension;
2382
+ this.entries = [];
2383
+ for (let i = 0; i < numEntries; i++) {
2384
+ const idLen = buffer.readUInt32BE(offset);
2385
+ offset += 4;
2386
+ const id = buffer.subarray(offset, offset + idLen).toString("utf-8");
2387
+ offset += idLen;
2388
+ const metaLen = buffer.readUInt32BE(offset);
2389
+ offset += 4;
2390
+ const metaStr = buffer.subarray(offset, offset + metaLen).toString("utf-8");
2391
+ offset += metaLen;
2392
+ const metadata = JSON.parse(metaStr);
2393
+ const vector = new Float32Array(dimension);
2394
+ for (let d = 0; d < dimension; d++) {
2395
+ vector[d] = buffer.readFloatBE(offset);
2396
+ offset += 4;
2397
+ }
2398
+ this.entries.push({ id, vector, metadata });
2399
+ }
2400
+ return true;
2401
+ } catch {
2402
+ return false;
2403
+ }
2404
+ }
2405
+ cosineSimilarity(a, b) {
2406
+ if (a.length !== b.length)
2407
+ return 0;
2408
+ let dot = 0;
2409
+ for (let i = 0; i < a.length; i++) {
2410
+ dot += a[i] * b[i];
2411
+ }
2412
+ return Math.max(-1, Math.min(1, dot));
2413
+ }
2414
+ normalizeL2(vector) {
2415
+ const norm = Math.sqrt(vector.reduce((sum, v) => sum + v * v, 0));
2416
+ if (norm === 0)
2417
+ return vector;
2418
+ return vector.map((v) => v / norm);
2419
+ }
2420
+ };
2421
+ exports2.VectorStore = VectorStore;
2422
+ }
2423
+ });
2424
+
2425
+ // ../ai/dist/rag/indexer.js
2426
+ var require_indexer = __commonJS({
2427
+ "../ai/dist/rag/indexer.js"(exports2) {
2428
+ "use strict";
2429
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
2430
+ if (k2 === void 0) k2 = k;
2431
+ var desc = Object.getOwnPropertyDescriptor(m, k);
2432
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
2433
+ desc = { enumerable: true, get: function() {
2434
+ return m[k];
2435
+ } };
2436
+ }
2437
+ Object.defineProperty(o, k2, desc);
2438
+ }) : (function(o, m, k, k2) {
2439
+ if (k2 === void 0) k2 = k;
2440
+ o[k2] = m[k];
2441
+ }));
2442
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
2443
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
2444
+ }) : function(o, v) {
2445
+ o["default"] = v;
2446
+ });
2447
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
2448
+ var ownKeys = function(o) {
2449
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
2450
+ var ar = [];
2451
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
2452
+ return ar;
2453
+ };
2454
+ return ownKeys(o);
2455
+ };
2456
+ return function(mod) {
2457
+ if (mod && mod.__esModule) return mod;
2458
+ var result = {};
2459
+ if (mod != null) {
2460
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
2461
+ }
2462
+ __setModuleDefault(result, mod);
2463
+ return result;
2464
+ };
2465
+ })();
2466
+ Object.defineProperty(exports2, "__esModule", { value: true });
2467
+ exports2.buildIndexes = buildIndexes;
2468
+ var fs2 = __importStar(require("fs"));
2469
+ var path2 = __importStar(require("path"));
2470
+ var crypto = __importStar(require("crypto"));
2471
+ var chunker_1 = require_chunker();
2472
+ var contextualizer_1 = require_contextualizer();
2473
+ var bm25_1 = require_bm25();
2474
+ var embedder_1 = require_embedder();
2475
+ var vector_store_1 = require_vector_store();
2476
+ var INDEX_FILE = ".iacmp/rag-index.json";
2477
+ var KNOWLEDGE_DIR = path2.join(__dirname, "../knowledge");
2478
+ function hashProjectStacks(projectDir) {
2479
+ const stacksDir = path2.join(projectDir, "stacks");
2480
+ if (!fs2.existsSync(stacksDir))
2481
+ return "empty";
2482
+ const findFiles = (dir) => {
2483
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
2484
+ const files2 = [];
2485
+ for (const e of entries) {
2486
+ const full = path2.join(dir, e.name);
2487
+ if (e.isDirectory())
2488
+ files2.push(...findFiles(full));
2489
+ else if (e.name.endsWith(".ts"))
2490
+ files2.push(full);
2491
+ }
2492
+ return files2.sort();
2493
+ };
2494
+ const files = findFiles(stacksDir);
2495
+ const content = files.map((f) => `${f}:${fs2.statSync(f).mtimeMs}`).join("\n");
2496
+ return crypto.createHash("sha256").update(content).digest("hex").slice(0, 12);
2497
+ }
2498
+ function loadPersistedProjectChunks(projectDir, currentHash) {
2499
+ const indexPath = path2.join(projectDir, INDEX_FILE);
2500
+ if (!fs2.existsSync(indexPath))
2501
+ return null;
2502
+ try {
2503
+ const data = JSON.parse(fs2.readFileSync(indexPath, "utf-8"));
2504
+ if (data.projectHash !== currentHash)
2505
+ return null;
2506
+ return data.chunks;
2507
+ } catch {
2508
+ return null;
2509
+ }
2510
+ }
2511
+ function saveProjectChunks(projectDir, hash, chunks) {
2512
+ const indexPath = path2.join(projectDir, INDEX_FILE);
2513
+ fs2.mkdirSync(path2.dirname(indexPath), { recursive: true });
2514
+ const data = {
2515
+ projectHash: hash,
2516
+ chunks,
2517
+ builtAt: (/* @__PURE__ */ new Date()).toISOString()
2518
+ };
2519
+ fs2.writeFileSync(indexPath, JSON.stringify(data, null, 2), "utf-8");
2520
+ }
2521
+ function loadKnowledgeChunks() {
2522
+ const chunks = [];
2523
+ if (!fs2.existsSync(KNOWLEDGE_DIR))
2524
+ return chunks;
2525
+ const platforms = ["aws", "azure", "gcp", "cross-cloud"];
2526
+ for (const platform of platforms) {
2527
+ const platformDir = path2.join(KNOWLEDGE_DIR, platform);
2528
+ if (!fs2.existsSync(platformDir))
2529
+ continue;
2530
+ const files = fs2.readdirSync(platformDir).filter((f) => f.endsWith(".md"));
2531
+ for (const file of files) {
2532
+ try {
2533
+ const fileChunks = (0, chunker_1.chunkKnowledgeFile)(path2.join(platformDir, file), platform);
2534
+ chunks.push(...fileChunks);
2535
+ } catch {
2536
+ }
2537
+ }
2538
+ }
2539
+ return chunks;
2540
+ }
2541
+ var VECTOR_INDEX_FILE = ".iacmp/vector-index.bin";
2542
+ async function buildIndexes(options) {
2543
+ const { projectDir, systemPromptTemplate, anthropicApiKey, voyageApiKey = process.env["VOYAGE_API_KEY"], useContextualRetrieval = !!anthropicApiKey, onProgress } = options;
2544
+ const log = (msg) => onProgress?.(msg);
2545
+ log("Indexando stacks do projeto...");
2546
+ const currentHash = hashProjectStacks(projectDir);
2547
+ let projectChunks = loadPersistedProjectChunks(projectDir, currentHash);
2548
+ if (!projectChunks) {
2549
+ log("Stacks mudaram \u2014 reindexando...");
2550
+ const stacksDir = path2.join(projectDir, "stacks");
2551
+ const rawChunks = [];
2552
+ if (fs2.existsSync(stacksDir)) {
2553
+ const findFiles = (dir) => {
2554
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
2555
+ const files = [];
2556
+ for (const e of entries) {
2557
+ const full = path2.join(dir, e.name);
2558
+ if (e.isDirectory())
2559
+ files.push(...findFiles(full));
2560
+ else if (e.name.endsWith(".ts"))
2561
+ files.push(full);
2562
+ }
2563
+ return files;
2564
+ };
2565
+ for (const file of findFiles(stacksDir)) {
2566
+ rawChunks.push(...(0, chunker_1.chunkStackFile)(file, projectDir));
2567
+ }
2568
+ }
2569
+ if (useContextualRetrieval && anthropicApiKey && rawChunks.length > 0) {
2570
+ log(`Aplicando Contextual Retrieval em ${rawChunks.length} chunks de stacks...`);
2571
+ const contextualizer = new contextualizer_1.Contextualizer(anthropicApiKey);
2572
+ const fullDocument = rawChunks.map((c) => c.content).join("\n\n");
2573
+ projectChunks = await contextualizer.enrichBatch(rawChunks, fullDocument, {
2574
+ concurrency: 5,
2575
+ onProgress: (done, total2) => log(` ${done}/${total2} chunks enriquecidos`)
2576
+ });
2577
+ } else {
2578
+ projectChunks = rawChunks;
2579
+ }
2580
+ saveProjectChunks(projectDir, currentHash, projectChunks);
2581
+ log(`${projectChunks.length} chunks de stacks indexados.`);
2582
+ } else {
2583
+ log(`${projectChunks.length} chunks de stacks carregados do cache.`);
2584
+ }
2585
+ log("Indexando documenta\xE7\xE3o de constructs...");
2586
+ let docsChunks = (0, chunker_1.chunkIacmpDocs)(systemPromptTemplate);
2587
+ if (useContextualRetrieval && anthropicApiKey && docsChunks.length > 0) {
2588
+ log(`Aplicando Contextual Retrieval em ${docsChunks.length} chunks de docs...`);
2589
+ const contextualizer = new contextualizer_1.Contextualizer(anthropicApiKey);
2590
+ const fullDoc = systemPromptTemplate;
2591
+ docsChunks = await contextualizer.enrichBatch(docsChunks, fullDoc, { concurrency: 5 });
2592
+ }
2593
+ log(`${docsChunks.length} chunks de docs indexados.`);
2594
+ log("Indexando base de conhecimento de plataforma...");
2595
+ const knowledgeChunks = loadKnowledgeChunks();
2596
+ log(`${knowledgeChunks.length} chunks de conhecimento indexados.`);
2597
+ const projectIndex = (0, bm25_1.buildBM25Index)(projectChunks);
2598
+ const docsIndex = (0, bm25_1.buildBM25Index)(docsChunks);
2599
+ const knowledgeIndex = (0, bm25_1.buildBM25Index)(knowledgeChunks);
2600
+ const chunkMap = /* @__PURE__ */ new Map();
2601
+ for (const c of [...projectChunks, ...docsChunks, ...knowledgeChunks]) {
2602
+ chunkMap.set(c.id, c);
2603
+ }
2604
+ const vectorStore = new vector_store_1.VectorStore();
2605
+ const vectorIndexPath = path2.join(projectDir, VECTOR_INDEX_FILE);
2606
+ if (voyageApiKey) {
2607
+ const loaded = vectorStore.load(vectorIndexPath);
2608
+ if (!loaded) {
2609
+ log(`Gerando embeddings com Voyage AI (${knowledgeChunks.length} chunks de conhecimento)...`);
2610
+ const embedder = (0, embedder_1.createEmbedder)(voyageApiKey);
2611
+ const texts = knowledgeChunks.map((c) => c.contextualContent ?? c.content);
2612
+ try {
2613
+ const vectors = await embedder.embed(texts);
2614
+ for (let i = 0; i < knowledgeChunks.length; i++) {
2615
+ const chunk = knowledgeChunks[i];
2616
+ vectorStore.add(chunk.id, vectors[i], {
2617
+ id: chunk.id,
2618
+ source: chunk.metadata.source,
2619
+ section: chunk.metadata.section,
2620
+ platform: chunk.metadata.platform
2621
+ });
2622
+ }
2623
+ vectorStore.save(vectorIndexPath);
2624
+ log(`${vectorStore.size()} vetores gerados e salvos.`);
2625
+ } catch (err) {
2626
+ log(`Embeddings Voyage AI falharam \u2014 usando apenas BM25: ${err.message}`);
2627
+ }
2628
+ } else {
2629
+ log(`${vectorStore.size()} vetores carregados do cache.`);
2630
+ }
2631
+ }
2632
+ const total = projectChunks.length + docsChunks.length + knowledgeChunks.length;
2633
+ log(`RAG pronto \u2014 ${total} chunks indexados no total${voyageApiKey ? ` + ${vectorStore.size()} vetores` : ""}.`);
2634
+ return { projectIndex, docsIndex, knowledgeIndex, chunkMap, vectorStore };
2635
+ }
2636
+ }
2637
+ });
2638
+
2639
+ // ../ai/dist/rag/retriever.js
2640
+ var require_retriever = __commonJS({
2641
+ "../ai/dist/rag/retriever.js"(exports2) {
2642
+ "use strict";
2643
+ Object.defineProperty(exports2, "__esModule", { value: true });
2644
+ exports2.retrieve = retrieve;
2645
+ exports2.formatRetrievedContext = formatRetrievedContext;
2646
+ var bm25_1 = require_bm25();
2647
+ var DEFAULT_K = {
2648
+ project: 5,
2649
+ docs: 3,
2650
+ knowledge: 5
2651
+ };
2652
+ function retrieve(indexes, query, options = {}) {
2653
+ const { projectK = DEFAULT_K.project, docsK = DEFAULT_K.docs, knowledgeK = DEFAULT_K.knowledge, minScore = 0.1 } = options;
2654
+ const results = [];
2655
+ const projectHits = (0, bm25_1.bm25Search)(indexes.projectIndex, query, projectK);
2656
+ const docsHits = (0, bm25_1.bm25Search)(indexes.docsIndex, query, docsK);
2657
+ const knowledgeHits = (0, bm25_1.bm25Search)(indexes.knowledgeIndex, query, knowledgeK);
2658
+ for (const hit of [...projectHits, ...docsHits, ...knowledgeHits]) {
2659
+ if (hit.score < minScore)
2660
+ continue;
2661
+ const chunk = indexes.chunkMap.get(hit.id);
2662
+ if (!chunk)
2663
+ continue;
2664
+ results.push({
2665
+ chunk,
2666
+ score: hit.score,
2667
+ source: chunk.metadata.source
2668
+ });
2669
+ }
2670
+ return results.sort((a, b) => b.score - a.score);
2671
+ }
2672
+ function formatRetrievedContext(results) {
2673
+ if (results.length === 0)
2674
+ return "";
2675
+ const sections = ["## Contexto recuperado pelo RAG\n"];
2676
+ const bySource = {
2677
+ "project-stack": results.filter((r) => r.chunk.metadata.source === "project-stack"),
2678
+ "iacmp-docs": results.filter((r) => r.chunk.metadata.source === "iacmp-docs"),
2679
+ "platform-knowledge": results.filter((r) => r.chunk.metadata.source === "platform-knowledge")
2680
+ };
2681
+ if (bySource["project-stack"].length > 0) {
2682
+ sections.push("### Stacks do projeto relevantes");
2683
+ for (const r of bySource["project-stack"]) {
2684
+ sections.push(r.chunk.content);
2685
+ sections.push("");
2686
+ }
2687
+ }
2688
+ if (bySource["iacmp-docs"].length > 0) {
2689
+ sections.push("### Documenta\xE7\xE3o de constructs relevante");
2690
+ for (const r of bySource["iacmp-docs"]) {
2691
+ sections.push(r.chunk.content);
2692
+ sections.push("");
2693
+ }
2694
+ }
2695
+ if (bySource["platform-knowledge"].length > 0) {
2696
+ sections.push("### Conhecimento de plataforma relevante");
2697
+ for (const r of bySource["platform-knowledge"]) {
2698
+ sections.push(r.chunk.content);
2699
+ sections.push("");
2700
+ }
2701
+ }
2702
+ return sections.join("\n");
2703
+ }
2704
+ }
2705
+ });
2706
+
2707
+ // ../ai/dist/rag/live-retriever.js
2708
+ var require_live_retriever = __commonJS({
2709
+ "../ai/dist/rag/live-retriever.js"(exports2) {
2710
+ "use strict";
2711
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
2712
+ if (k2 === void 0) k2 = k;
2713
+ var desc = Object.getOwnPropertyDescriptor(m, k);
2714
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
2715
+ desc = { enumerable: true, get: function() {
2716
+ return m[k];
2717
+ } };
2718
+ }
2719
+ Object.defineProperty(o, k2, desc);
2720
+ }) : (function(o, m, k, k2) {
2721
+ if (k2 === void 0) k2 = k;
2722
+ o[k2] = m[k];
2723
+ }));
2724
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
2725
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
2726
+ }) : function(o, v) {
2727
+ o["default"] = v;
2728
+ });
2729
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
2730
+ var ownKeys = function(o) {
2731
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
2732
+ var ar = [];
2733
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
2734
+ return ar;
2735
+ };
2736
+ return ownKeys(o);
2737
+ };
2738
+ return function(mod) {
2739
+ if (mod && mod.__esModule) return mod;
2740
+ var result = {};
2741
+ if (mod != null) {
2742
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
2743
+ }
2744
+ __setModuleDefault(result, mod);
2745
+ return result;
2746
+ };
2747
+ })();
2748
+ Object.defineProperty(exports2, "__esModule", { value: true });
2749
+ exports2.LIVE_SIGNALS = void 0;
2750
+ exports2.fetchLive = fetchLive;
2751
+ exports2.shouldFetchLive = shouldFetchLive;
2752
+ var fs2 = __importStar(require("fs"));
2753
+ var path2 = __importStar(require("path"));
2754
+ var CACHE_FILE = ".iacmp/live-cache.json";
2755
+ var CACHE_TTL_MS = 60 * 60 * 1e3;
2756
+ var FETCH_TIMEOUT_MS = 3e3;
2757
+ function loadCache(projectDir) {
2758
+ const filePath = projectDir ? path2.join(projectDir, CACHE_FILE) : path2.join(process.cwd(), CACHE_FILE);
2759
+ if (!fs2.existsSync(filePath))
2760
+ return {};
2761
+ try {
2762
+ return JSON.parse(fs2.readFileSync(filePath, "utf-8"));
2763
+ } catch {
2764
+ return {};
2765
+ }
2766
+ }
2767
+ function saveCache(store, projectDir) {
2768
+ const filePath = projectDir ? path2.join(projectDir, CACHE_FILE) : path2.join(process.cwd(), CACHE_FILE);
2769
+ try {
2770
+ fs2.mkdirSync(path2.dirname(filePath), { recursive: true });
2771
+ fs2.writeFileSync(filePath, JSON.stringify(store, null, 2), "utf-8");
2772
+ } catch {
2773
+ }
2774
+ }
2775
+ function getCached2(store, key) {
2776
+ const entry = store[key];
2777
+ if (!entry)
2778
+ return null;
2779
+ if (Date.now() > entry.expiresAt)
2780
+ return null;
2781
+ return entry.value;
2782
+ }
2783
+ function setCached(store, key, value) {
2784
+ store[key] = { value, expiresAt: Date.now() + CACHE_TTL_MS };
2785
+ const now = Date.now();
2786
+ for (const k of Object.keys(store)) {
2787
+ if (store[k].expiresAt < now) {
2788
+ delete store[k];
2789
+ }
2790
+ }
2791
+ }
2792
+ async function fetchWithTimeout(url, options = {}) {
2793
+ const controller = new AbortController();
2794
+ const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
2795
+ try {
2796
+ const resp = await fetch(url, { ...options, signal: controller.signal });
2797
+ if (!resp.ok)
2798
+ return "";
2799
+ return await resp.text();
2800
+ } catch {
2801
+ return "";
2802
+ } finally {
2803
+ clearTimeout(timer);
2804
+ }
2805
+ }
2806
+ function parseRssText(xml, maxItems = 5) {
2807
+ const items = [];
2808
+ const itemRegex = /<item[^>]*>([\s\S]*?)<\/item>/gi;
2809
+ const titleRegex = /<title[^>]*><!\[CDATA\[(.*?)\]\]><\/title>|<title[^>]*>(.*?)<\/title>/i;
2810
+ const descRegex = /<description[^>]*><!\[CDATA\[(.*?)\]\]><\/description>|<description[^>]*>(.*?)<\/description>/i;
2811
+ let match;
2812
+ let count = 0;
2813
+ while ((match = itemRegex.exec(xml)) !== null && count < maxItems) {
2814
+ const itemContent = match[1];
2815
+ const titleMatch = titleRegex.exec(itemContent);
2816
+ const descMatch = descRegex.exec(itemContent);
2817
+ const title = (titleMatch?.[1] ?? titleMatch?.[2] ?? "").trim();
2818
+ const desc = (descMatch?.[1] ?? descMatch?.[2] ?? "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim().slice(0, 200);
2819
+ if (title) {
2820
+ items.push(desc ? `- ${title}: ${desc}` : `- ${title}`);
2821
+ count++;
2822
+ }
2823
+ }
2824
+ return items.join("\n");
2825
+ }
2826
+ function mentionsPrice(query) {
2827
+ const lower = query.toLowerCase();
2828
+ return ["pre\xE7o", "preco", "custo", "quanto custa", "valor", "cost", "price", "pricing"].some((s) => lower.includes(s));
2829
+ }
2830
+ function mentionsTerraform(query) {
2831
+ const lower = query.toLowerCase();
2832
+ return ["terraform", "tf provider", "terraform provider", "hashicorp"].some((s) => lower.includes(s));
2833
+ }
2834
+ function mentionsRecent(query) {
2835
+ const lower = query.toLowerCase();
2836
+ return ["lan\xE7ou", "lancou", "novidade", "recente", "novo servi\xE7o", "novo recurso", "anunciou", "what's new", "whats new"].some((s) => lower.includes(s));
2837
+ }
2838
+ function mentionsAzure(query) {
2839
+ const lower = query.toLowerCase();
2840
+ return ["azure", "microsoft azure", "az "].some((s) => lower.includes(s));
2841
+ }
2842
+ function mentionsGcp(query) {
2843
+ const lower = query.toLowerCase();
2844
+ return ["gcp", "google cloud", "gcloud", "cloud run", "bigquery", "cloud functions", "pub/sub", "pubsub", "spanner"].some((s) => lower.includes(s));
2845
+ }
2846
+ function extractAzureServiceName(query) {
2847
+ const lower = query.toLowerCase();
2848
+ const serviceMap = [
2849
+ [["functions", "function app"], "Azure Functions"],
2850
+ [["app service", "web app"], "Azure App Service"],
2851
+ [["sql database", "azure sql"], "SQL Database"],
2852
+ [["cosmos", "cosmosdb"], "Azure Cosmos DB"],
2853
+ [["blob", "storage account"], "Storage"],
2854
+ [["kubernetes", "aks"], "Azure Kubernetes Service"],
2855
+ [["container instance", "aci"], "Container Instances"],
2856
+ [["virtual machine", "vm ", "vms "], "Virtual Machines"],
2857
+ [["redis", "cache"], "Azure Cache for Redis"],
2858
+ [["service bus"], "Service Bus"],
2859
+ [["event hub"], "Event Hubs"],
2860
+ [["api management", "apim"], "API Management"],
2861
+ [["postgresql", "postgres"], "Azure Database for PostgreSQL"],
2862
+ [["mysql"], "Azure Database for MySQL"]
2863
+ ];
2864
+ for (const [terms, serviceName] of serviceMap) {
2865
+ if (terms.some((t) => lower.includes(t)))
2866
+ return serviceName;
2867
+ }
2868
+ return null;
2869
+ }
2870
+ function extractGcpServiceId(query) {
2871
+ const lower = query.toLowerCase();
2872
+ const serviceMap = [
2873
+ [["cloud run"], "Cloud Run"],
2874
+ [["cloud functions", "functions"], "Cloud Functions"],
2875
+ [["bigquery"], "BigQuery"],
2876
+ [["gke", "kubernetes", "kubernetes engine"], "Kubernetes Engine"],
2877
+ [["cloud sql", "sql"], "Cloud SQL"],
2878
+ [["spanner"], "Cloud Spanner"],
2879
+ [["pub/sub", "pubsub"], "Cloud Pub/Sub"],
2880
+ [["compute engine", "vm ", "inst\xE2ncia"], "Compute Engine"],
2881
+ [["cloud storage", "gcs"], "Cloud Storage"],
2882
+ [["cloud bigtable", "bigtable"], "Cloud Bigtable"]
2883
+ ];
2884
+ for (const [terms, serviceId] of serviceMap) {
2885
+ if (terms.some((t) => lower.includes(t)))
2886
+ return serviceId;
2887
+ }
2888
+ return null;
2889
+ }
2890
+ async function fetchAwsWhatsNew(cache) {
2891
+ const cacheKey = "aws-whats-new";
2892
+ const cached = getCached2(cache, cacheKey);
2893
+ if (cached !== null)
2894
+ return cached;
2895
+ const xml = await fetchWithTimeout("https://aws.amazon.com/about-aws/whats-new/recent/feed/");
2896
+ if (!xml)
2897
+ return "";
2898
+ const text = parseRssText(xml, 5);
2899
+ const result = text ? `### AWS What's New (recente)
2900
+ ${text}` : "";
2901
+ setCached(cache, cacheKey, result);
2902
+ return result;
2903
+ }
2904
+ async function fetchAwsPricing(query, cache) {
2905
+ const sections = [];
2906
+ if (query.toLowerCase().includes("lambda")) {
2907
+ const cacheKey = "aws-pricing-lambda";
2908
+ const cached = getCached2(cache, cacheKey);
2909
+ if (cached !== null) {
2910
+ if (cached)
2911
+ sections.push(cached);
2912
+ } else {
2913
+ const url = "https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AWSLambda/current/us-east-1/index.json";
2914
+ const raw = await fetchWithTimeout(url);
2915
+ let result = "";
2916
+ if (raw) {
2917
+ try {
2918
+ const data = JSON.parse(raw);
2919
+ const pricePoints = [];
2920
+ if (data.terms?.OnDemand) {
2921
+ let count = 0;
2922
+ for (const sku of Object.values(data.terms.OnDemand)) {
2923
+ for (const term of Object.values(sku)) {
2924
+ for (const dim of Object.values(term.priceDimensions ?? {})) {
2925
+ const usd = dim.pricePerUnit?.USD;
2926
+ const desc = dim.description;
2927
+ if (usd && desc && count < 3) {
2928
+ pricePoints.push(` - ${desc}: $${usd}`);
2929
+ count++;
2930
+ }
2931
+ }
2932
+ }
2933
+ }
2934
+ }
2935
+ if (pricePoints.length > 0) {
2936
+ result = `### AWS Lambda Pricing (us-east-1)
2937
+ ${pricePoints.join("\n")}`;
2938
+ }
2939
+ } catch {
2940
+ }
2941
+ }
2942
+ setCached(cache, cacheKey, result);
2943
+ if (result)
2944
+ sections.push(result);
2945
+ }
2946
+ }
2947
+ if (query.toLowerCase().includes("rds") || query.toLowerCase().includes("aurora")) {
2948
+ const cacheKey = "aws-pricing-rds-note";
2949
+ const cached = getCached2(cache, cacheKey);
2950
+ if (cached !== null) {
2951
+ if (cached)
2952
+ sections.push(cached);
2953
+ } else {
2954
+ const result = `### AWS RDS Pricing
2955
+ Pre\xE7os variam por engine (MySQL, PostgreSQL, Oracle, SQL Server, Aurora), tipo de inst\xE2ncia e regi\xE3o.
2956
+ Calculadora oficial: https://aws.amazon.com/rds/pricing/
2957
+ Endpoint JSON: https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonRDS/current/index.json`;
2958
+ setCached(cache, cacheKey, result);
2959
+ sections.push(result);
2960
+ }
2961
+ }
2962
+ return sections.join("\n\n");
2963
+ }
2964
+ async function fetchAzurePricing(query, cache) {
2965
+ const serviceName = extractAzureServiceName(query);
2966
+ if (!serviceName)
2967
+ return "";
2968
+ const cacheKey = `azure-pricing-${serviceName.toLowerCase().replace(/\s+/g, "-")}`;
2969
+ const cached = getCached2(cache, cacheKey);
2970
+ if (cached !== null)
2971
+ return cached;
2972
+ const filter = encodeURIComponent(`serviceName eq '${serviceName}' and armRegionName eq 'eastus' and priceType eq 'Consumption'`);
2973
+ const url = `https://prices.azure.com/api/retail/prices?$filter=${filter}&$top=10`;
2974
+ const raw = await fetchWithTimeout(url);
2975
+ if (!raw)
2976
+ return "";
2977
+ try {
2978
+ const data = JSON.parse(raw);
2979
+ if (!data.Items || data.Items.length === 0)
2980
+ return "";
2981
+ const lines = [`### Azure ${serviceName} Pricing (East US)`];
2982
+ let count = 0;
2983
+ for (const item of data.Items) {
2984
+ if (count >= 6)
2985
+ break;
2986
+ const sku = item.skuName ?? item.productName ?? "";
2987
+ const price = item.retailPrice;
2988
+ const unit = item.unitOfMeasure ?? "";
2989
+ if (sku && price !== void 0) {
2990
+ lines.push(` - ${sku}: $${price}/${unit}`);
2991
+ count++;
2992
+ }
2993
+ }
2994
+ if (lines.length <= 1)
2995
+ return "";
2996
+ const result = lines.join("\n");
2997
+ setCached(cache, cacheKey, result);
2998
+ return result;
2999
+ } catch {
3000
+ return "";
3001
+ }
3002
+ }
3003
+ async function fetchAzureUpdates(cache) {
3004
+ const cacheKey = "azure-updates";
3005
+ const cached = getCached2(cache, cacheKey);
3006
+ if (cached !== null)
3007
+ return cached;
3008
+ const xml = await fetchWithTimeout("https://www.microsoft.com/releasecommunications/api/v2/azure/rss");
3009
+ if (!xml)
3010
+ return "";
3011
+ const text = parseRssText(xml, 5);
3012
+ const result = text ? `### Azure Updates (recente)
3013
+ ${text}` : "";
3014
+ setCached(cache, cacheKey, result);
3015
+ return result;
3016
+ }
3017
+ async function fetchGcpPricing(query, cache) {
3018
+ const targetService = extractGcpServiceId(query);
3019
+ if (!targetService)
3020
+ return "";
3021
+ const cacheKey = `gcp-pricing-${targetService.toLowerCase().replace(/\s+/g, "-")}`;
3022
+ const cached = getCached2(cache, cacheKey);
3023
+ if (cached !== null)
3024
+ return cached;
3025
+ const servicesRaw = await fetchWithTimeout("https://cloudbilling.googleapis.com/v1/services?pageSize=200");
3026
+ if (!servicesRaw)
3027
+ return "";
3028
+ let serviceId = null;
3029
+ try {
3030
+ const servicesData = JSON.parse(servicesRaw);
3031
+ const match = (servicesData.services ?? []).find((s) => s.displayName?.toLowerCase().includes(targetService.toLowerCase()));
3032
+ if (match?.name) {
3033
+ serviceId = match.name;
3034
+ }
3035
+ } catch {
3036
+ return "";
3037
+ }
3038
+ if (!serviceId)
3039
+ return "";
3040
+ const skusRaw = await fetchWithTimeout(`https://cloudbilling.googleapis.com/v1/${serviceId}/skus?pageSize=10&currencyCode=USD`);
3041
+ if (!skusRaw)
3042
+ return "";
3043
+ try {
3044
+ const skusData = JSON.parse(skusRaw);
3045
+ if (!skusData.skus || skusData.skus.length === 0)
3046
+ return "";
3047
+ const lines = [`### GCP ${targetService} Pricing (USD)`];
3048
+ let count = 0;
3049
+ for (const sku of skusData.skus) {
3050
+ if (count >= 6)
3051
+ break;
3052
+ const desc = sku.description;
3053
+ const rate = sku.pricingInfo?.[0]?.pricingExpression?.tieredRates?.[0];
3054
+ const unit = sku.pricingInfo?.[0]?.pricingExpression?.usageUnit ?? "";
3055
+ if (desc && rate?.unitPrice) {
3056
+ const units = Number(rate.unitPrice.units ?? 0);
3057
+ const nanos = (rate.unitPrice.nanos ?? 0) / 1e9;
3058
+ const price = units + nanos;
3059
+ lines.push(` - ${desc}: $${price.toFixed(6)}/${unit}`);
3060
+ count++;
3061
+ }
3062
+ }
3063
+ if (lines.length <= 1)
3064
+ return "";
3065
+ const result = lines.join("\n");
3066
+ setCached(cache, cacheKey, result);
3067
+ return result;
3068
+ } catch {
3069
+ return "";
3070
+ }
3071
+ }
3072
+ async function fetchGcpReleaseNotes(cache) {
3073
+ const cacheKey = "gcp-release-notes";
3074
+ const cached = getCached2(cache, cacheKey);
3075
+ if (cached !== null)
3076
+ return cached;
3077
+ const xml = await fetchWithTimeout("https://cloud.google.com/feeds/gcp-release-notes.xml");
3078
+ if (!xml)
3079
+ return "";
3080
+ const text = parseAtomText(xml, 5);
3081
+ const result = text ? `### GCP Release Notes (recente)
3082
+ ${text}` : "";
3083
+ setCached(cache, cacheKey, result);
3084
+ return result;
3085
+ }
3086
+ function parseAtomText(xml, maxItems = 5) {
3087
+ const items = [];
3088
+ const entryRegex = /<entry[^>]*>([\s\S]*?)<\/entry>/gi;
3089
+ const titleRegex = /<title[^>]*>(.*?)<\/title>/i;
3090
+ const summaryRegex = /<summary[^>]*>([\s\S]*?)<\/summary>/i;
3091
+ let match;
3092
+ let count = 0;
3093
+ while ((match = entryRegex.exec(xml)) !== null && count < maxItems) {
3094
+ const entryContent = match[1];
3095
+ const titleMatch = titleRegex.exec(entryContent);
3096
+ const summaryMatch = summaryRegex.exec(entryContent);
3097
+ const title = (titleMatch?.[1] ?? "").replace(/<[^>]+>/g, "").trim();
3098
+ const summary = (summaryMatch?.[1] ?? "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim().slice(0, 200);
3099
+ if (title) {
3100
+ items.push(summary ? `- ${title}: ${summary}` : `- ${title}`);
3101
+ count++;
3102
+ }
3103
+ }
3104
+ return items.join("\n");
3105
+ }
3106
+ async function fetchTerraformProviderVersion(cache) {
3107
+ const cacheKey = "tf-aws-provider-version";
3108
+ const cached = getCached2(cache, cacheKey);
3109
+ if (cached !== null)
3110
+ return cached;
3111
+ const raw = await fetchWithTimeout("https://registry.terraform.io/v1/providers/hashicorp/aws");
3112
+ if (!raw)
3113
+ return "";
3114
+ try {
3115
+ const data = JSON.parse(raw);
3116
+ const version = data.version;
3117
+ if (!version)
3118
+ return "";
3119
+ const result = `### Terraform AWS Provider
3120
+ Vers\xE3o atual: ${version}
3121
+ Documenta\xE7\xE3o: https://registry.terraform.io/providers/hashicorp/aws/latest/docs`;
3122
+ setCached(cache, cacheKey, result);
3123
+ return result;
3124
+ } catch {
3125
+ return "";
3126
+ }
3127
+ }
3128
+ async function fetchLive(query, signals, options = {}) {
3129
+ const cache = loadCache(options.projectDir);
3130
+ const parts = [];
3131
+ const sigSet = new Set(signals);
3132
+ try {
3133
+ const isRecent = mentionsRecent(query) || sigSet.has("recent");
3134
+ const isPrice = mentionsPrice(query) || sigSet.has("price");
3135
+ const isAzure = mentionsAzure(query) || sigSet.has("azure");
3136
+ const isGcp = mentionsGcp(query) || sigSet.has("gcp");
3137
+ const isTf = mentionsTerraform(query) || sigSet.has("terraform");
3138
+ const fetches = [];
3139
+ if (isRecent && !isAzure && !isGcp)
3140
+ fetches.push(fetchAwsWhatsNew(cache));
3141
+ if (isPrice && !isAzure && !isGcp)
3142
+ fetches.push(fetchAwsPricing(query, cache));
3143
+ if (isPrice && isAzure)
3144
+ fetches.push(fetchAzurePricing(query, cache));
3145
+ if (isRecent && isAzure)
3146
+ fetches.push(fetchAzureUpdates(cache));
3147
+ if (isPrice && isGcp)
3148
+ fetches.push(fetchGcpPricing(query, cache));
3149
+ if (isRecent && isGcp)
3150
+ fetches.push(fetchGcpReleaseNotes(cache));
3151
+ if (isTf)
3152
+ fetches.push(fetchTerraformProviderVersion(cache));
3153
+ const results = await Promise.all(fetches);
3154
+ for (const r of results) {
3155
+ if (r)
3156
+ parts.push(r);
3157
+ }
3158
+ } finally {
3159
+ saveCache(cache, options.projectDir);
3160
+ }
3161
+ return parts.join("\n\n");
3162
+ }
3163
+ exports2.LIVE_SIGNALS = [
3164
+ // Preço / custo
3165
+ "pre\xE7o",
3166
+ "preco",
3167
+ "custo",
3168
+ "quanto custa",
3169
+ "valor",
3170
+ "pricing",
3171
+ // Novidades / recente
3172
+ "lan\xE7ou",
3173
+ "lancou",
3174
+ "novidade",
3175
+ "recente",
3176
+ "novo servi\xE7o",
3177
+ "novo recurso",
3178
+ "anunciou",
3179
+ "vers\xE3o atual",
3180
+ "versao atual",
3181
+ "what's new",
3182
+ "whats new",
3183
+ "release notes",
3184
+ "release note",
3185
+ // Terraform
3186
+ "terraform provider",
3187
+ "terraform aws",
3188
+ "terraform azure",
3189
+ "terraform gcp",
3190
+ // Azure (específicos que indicam contexto Azure + info ao vivo)
3191
+ "azure functions pre\xE7o",
3192
+ "app service custo",
3193
+ "cosmos db custo",
3194
+ "azure sql pre\xE7o",
3195
+ // GCP (específicos)
3196
+ "cloud run pre\xE7o",
3197
+ "bigquery custo",
3198
+ "gke pre\xE7o",
3199
+ "cloud sql gcp"
3200
+ ];
3201
+ function shouldFetchLive(query) {
3202
+ const lower = query.toLowerCase();
3203
+ return exports2.LIVE_SIGNALS.some((s) => lower.includes(s));
3204
+ }
3205
+ }
3206
+ });
3207
+
3208
+ // ../ai/dist/tools/context-reader.js
3209
+ var require_context_reader = __commonJS({
3210
+ "../ai/dist/tools/context-reader.js"(exports2) {
3211
+ "use strict";
3212
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
3213
+ if (k2 === void 0) k2 = k;
3214
+ var desc = Object.getOwnPropertyDescriptor(m, k);
3215
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
3216
+ desc = { enumerable: true, get: function() {
3217
+ return m[k];
3218
+ } };
3219
+ }
3220
+ Object.defineProperty(o, k2, desc);
3221
+ }) : (function(o, m, k, k2) {
3222
+ if (k2 === void 0) k2 = k;
3223
+ o[k2] = m[k];
3224
+ }));
3225
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
3226
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
3227
+ }) : function(o, v) {
3228
+ o["default"] = v;
3229
+ });
3230
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
3231
+ var ownKeys = function(o) {
3232
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
3233
+ var ar = [];
3234
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
3235
+ return ar;
3236
+ };
3237
+ return ownKeys(o);
3238
+ };
3239
+ return function(mod) {
3240
+ if (mod && mod.__esModule) return mod;
3241
+ var result = {};
3242
+ if (mod != null) {
3243
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
3244
+ }
3245
+ __setModuleDefault(result, mod);
3246
+ return result;
3247
+ };
3248
+ })();
3249
+ Object.defineProperty(exports2, "__esModule", { value: true });
3250
+ exports2.readProjectMeta = readProjectMeta;
3251
+ exports2.readProjectContext = readProjectContext2;
3252
+ exports2.readProjectContextRAG = readProjectContextRAG;
3253
+ exports2.invalidateIndexCache = invalidateIndexCache;
3254
+ var fs2 = __importStar(require("fs"));
3255
+ var path2 = __importStar(require("path"));
3256
+ var indexer_1 = require_indexer();
3257
+ var retriever_1 = require_retriever();
3258
+ var system_prompt_1 = require_system_prompt();
3259
+ var live_retriever_1 = require_live_retriever();
3260
+ var indexCache = /* @__PURE__ */ new Map();
3261
+ function readProjectMeta(projectDir) {
3262
+ const lines = [];
3263
+ const configPath = path2.join(projectDir, "iacmp.json");
3264
+ if (fs2.existsSync(configPath)) {
3265
+ try {
3266
+ const config = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
3267
+ lines.push("## Configura\xE7\xE3o do projeto (iacmp.json)");
3268
+ lines.push(`- Provider: ${config["provider"] ?? "aws"}`);
3269
+ lines.push(`- Regi\xE3o: ${config["region"] ?? "us-east-1"}`);
3270
+ lines.push(`- Linguagem: ${config["language"] ?? "typescript"}`);
3271
+ lines.push(`- Nome: ${config["name"] ?? path2.basename(projectDir)}`);
3272
+ lines.push("");
3273
+ } catch {
3274
+ lines.push("iacmp.json encontrado mas inv\xE1lido.");
3275
+ lines.push("");
3276
+ }
3277
+ } else {
3278
+ lines.push("Nenhum iacmp.json encontrado \u2014 projeto n\xE3o inicializado.");
3279
+ lines.push("");
3280
+ }
3281
+ const stacksDir = path2.join(projectDir, "stacks");
3282
+ if (fs2.existsSync(stacksDir)) {
3283
+ const findStackFiles = (dir) => {
3284
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
3285
+ const files = [];
3286
+ for (const e of entries) {
3287
+ const full = path2.join(dir, e.name);
3288
+ if (e.isDirectory())
3289
+ files.push(...findStackFiles(full));
3290
+ else if (e.name.endsWith(".ts") || e.name.endsWith(".js"))
3291
+ files.push(full);
3292
+ }
3293
+ return files;
3294
+ };
3295
+ const stackFiles = findStackFiles(stacksDir);
3296
+ if (stackFiles.length > 0) {
3297
+ lines.push("## Stacks existentes");
3298
+ lines.push("IMPORTANTE: Estas s\xE3o as stacks reais do projeto. Ao modificar ou mover recursos, use exatamente estes caminhos \u2014 n\xE3o crie arquivos novos se o destino j\xE1 existe.");
3299
+ for (const filePath of stackFiles) {
3300
+ const rel = path2.relative(projectDir, filePath);
3301
+ lines.push(`
3302
+ ### ${rel}`);
3303
+ lines.push("```typescript");
3304
+ lines.push(fs2.readFileSync(filePath, "utf-8").trimEnd());
3305
+ lines.push("```");
3306
+ }
3307
+ lines.push("");
3308
+ } else {
3309
+ lines.push("## Stacks existentes\nNenhuma stack encontrada em stacks/.");
3310
+ lines.push("");
3311
+ }
3312
+ } else {
3313
+ lines.push("Diret\xF3rio stacks/ n\xE3o encontrado.");
3314
+ lines.push("");
3315
+ }
3316
+ return lines.join("\n");
3317
+ }
3318
+ function readProjectContext2(projectDir) {
3319
+ const lines = [];
3320
+ const configPath = path2.join(projectDir, "iacmp.json");
3321
+ if (fs2.existsSync(configPath)) {
3322
+ try {
3323
+ const config = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
3324
+ lines.push("## Configura\xE7\xE3o do projeto (iacmp.json)");
3325
+ lines.push(`- Provider: ${config["provider"] ?? "aws"}`);
3326
+ lines.push(`- Regi\xE3o: ${config["region"] ?? "us-east-1"}`);
3327
+ lines.push(`- Linguagem: ${config["language"] ?? "typescript"}`);
3328
+ lines.push(`- Nome: ${config["name"] ?? path2.basename(projectDir)}`);
3329
+ lines.push("");
3330
+ } catch {
3331
+ lines.push("iacmp.json encontrado mas inv\xE1lido.");
3332
+ lines.push("");
3333
+ }
3334
+ } else {
3335
+ lines.push("Nenhum iacmp.json encontrado \u2014 projeto n\xE3o inicializado.");
3336
+ lines.push("");
3337
+ }
3338
+ const stacksDir = path2.join(projectDir, "stacks");
3339
+ if (fs2.existsSync(stacksDir)) {
3340
+ const findStackFiles = (dir) => {
3341
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
3342
+ const files = [];
3343
+ for (const e of entries) {
3344
+ const full = path2.join(dir, e.name);
3345
+ if (e.isDirectory())
3346
+ files.push(...findStackFiles(full));
3347
+ else if (e.name.endsWith(".ts") || e.name.endsWith(".js"))
3348
+ files.push(full);
3349
+ }
3350
+ return files;
3351
+ };
3352
+ const stackFiles = findStackFiles(stacksDir);
3353
+ if (stackFiles.length > 0) {
3354
+ lines.push("## Stacks existentes");
3355
+ lines.push('Caminhos completos (use exatamente estes em "deletions"):');
3356
+ for (const filePath of stackFiles) {
3357
+ const rel = path2.relative(projectDir, filePath);
3358
+ const stat = fs2.statSync(filePath);
3359
+ lines.push(`- ${rel} (${(stat.size / 1024).toFixed(1)} KB)`);
3360
+ const content = fs2.readFileSync(filePath, "utf-8");
3361
+ if (content.split("\n").length <= 200) {
3362
+ lines.push("```typescript");
3363
+ lines.push(content);
3364
+ lines.push("```");
3365
+ }
3366
+ }
3367
+ lines.push("");
3368
+ } else {
3369
+ lines.push("## Stacks existentes\nNenhuma stack encontrada em stacks/.");
3370
+ lines.push("");
3371
+ }
3372
+ } else {
3373
+ lines.push("Diret\xF3rio stacks/ n\xE3o encontrado.");
3374
+ lines.push("");
3375
+ }
3376
+ return lines.join("\n");
3377
+ }
3378
+ async function readProjectContextRAG(projectDir, userQuery, options = {}) {
3379
+ const { anthropicApiKey, useContextualRetrieval, onProgress } = options;
3380
+ try {
3381
+ const indexerOptions = {
3382
+ projectDir,
3383
+ systemPromptTemplate: system_prompt_1.SYSTEM_PROMPT_TEMPLATE,
3384
+ anthropicApiKey,
3385
+ useContextualRetrieval,
3386
+ onProgress: onProgress ?? (() => {
3387
+ })
3388
+ };
3389
+ const indexes = await (0, indexer_1.buildIndexes)(indexerOptions);
3390
+ indexCache.set(projectDir, indexes);
3391
+ const results = (0, retriever_1.retrieve)(indexes, userQuery, {
3392
+ projectK: 5,
3393
+ docsK: 3,
3394
+ knowledgeK: 5,
3395
+ minScore: 0.05
3396
+ });
3397
+ const ragContext = (0, retriever_1.formatRetrievedContext)(results);
3398
+ const meta = readProjectMeta(projectDir);
3399
+ let liveContext = "";
3400
+ if ((0, live_retriever_1.shouldFetchLive)(userQuery)) {
3401
+ liveContext = await (0, live_retriever_1.fetchLive)(userQuery, [], { projectDir });
3402
+ }
3403
+ if (!ragContext && !liveContext) {
3404
+ return readProjectContext2(projectDir);
3405
+ }
3406
+ const parts = [meta];
3407
+ if (ragContext)
3408
+ parts.push(ragContext);
3409
+ if (liveContext)
3410
+ parts.push(`## Informa\xE7\xF5es ao vivo
3411
+ ${liveContext}`);
3412
+ return parts.join("\n");
3413
+ } catch {
3414
+ return readProjectContext2(projectDir);
3415
+ }
3416
+ }
3417
+ function invalidateIndexCache(projectDir) {
3418
+ if (projectDir) {
3419
+ indexCache.delete(projectDir);
3420
+ } else {
3421
+ indexCache.clear();
3422
+ }
3423
+ }
3424
+ }
3425
+ });
3426
+
3427
+ // ../ai/dist/tools/session-store.js
3428
+ var require_session_store = __commonJS({
3429
+ "../ai/dist/tools/session-store.js"(exports2) {
3430
+ "use strict";
3431
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
3432
+ if (k2 === void 0) k2 = k;
3433
+ var desc = Object.getOwnPropertyDescriptor(m, k);
3434
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
3435
+ desc = { enumerable: true, get: function() {
3436
+ return m[k];
3437
+ } };
3438
+ }
3439
+ Object.defineProperty(o, k2, desc);
3440
+ }) : (function(o, m, k, k2) {
3441
+ if (k2 === void 0) k2 = k;
3442
+ o[k2] = m[k];
3443
+ }));
3444
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
3445
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
3446
+ }) : function(o, v) {
3447
+ o["default"] = v;
3448
+ });
3449
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
3450
+ var ownKeys = function(o) {
3451
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
3452
+ var ar = [];
3453
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
3454
+ return ar;
3455
+ };
3456
+ return ownKeys(o);
3457
+ };
3458
+ return function(mod) {
3459
+ if (mod && mod.__esModule) return mod;
3460
+ var result = {};
3461
+ if (mod != null) {
3462
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
3463
+ }
3464
+ __setModuleDefault(result, mod);
3465
+ return result;
3466
+ };
3467
+ })();
3468
+ Object.defineProperty(exports2, "__esModule", { value: true });
3469
+ exports2.loadSession = loadSession;
3470
+ exports2.saveSession = saveSession;
3471
+ exports2.clearSession = clearSession;
3472
+ var fs2 = __importStar(require("fs"));
3473
+ var path2 = __importStar(require("path"));
3474
+ var crypto = __importStar(require("crypto"));
3475
+ var SESSION_FILE = ".iacmp/session.json";
3476
+ var MAX_MESSAGES = 20;
3477
+ function sessionPath(projectDir) {
3478
+ return path2.join(projectDir, SESSION_FILE);
3479
+ }
3480
+ function hashProject(projectDir) {
3481
+ const stacksDir = path2.join(projectDir, "stacks");
3482
+ if (!fs2.existsSync(stacksDir))
3483
+ return "empty";
3484
+ const findFiles = (dir) => {
3485
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
3486
+ const files = [];
3487
+ for (const e of entries) {
3488
+ const full = path2.join(dir, e.name);
3489
+ if (e.isDirectory())
3490
+ files.push(...findFiles(full));
3491
+ else if (e.name.endsWith(".ts"))
3492
+ files.push(path2.relative(projectDir, full));
3493
+ }
3494
+ return files.sort();
3495
+ };
3496
+ return crypto.createHash("sha256").update(findFiles(stacksDir).join("\n")).digest("hex").slice(0, 8);
3497
+ }
3498
+ function loadSession(projectDir) {
3499
+ const file = sessionPath(projectDir);
3500
+ if (!fs2.existsSync(file))
3501
+ return [];
3502
+ try {
3503
+ const data = JSON.parse(fs2.readFileSync(file, "utf-8"));
3504
+ const currentHash = hashProject(projectDir);
3505
+ if (data.projectHash && data.projectHash !== currentHash) {
3506
+ return [];
3507
+ }
3508
+ const messages = data.messages ?? [];
3509
+ for (let i = 0; i < messages.length - 1; i++) {
3510
+ if (messages[i].role === "user" && messages[i + 1].role === "user")
3511
+ return [];
3512
+ }
3513
+ if (messages.length > 0 && messages[messages.length - 1].role === "user")
3514
+ return [];
3515
+ return messages;
3516
+ } catch {
3517
+ return [];
3518
+ }
3519
+ }
3520
+ function saveSession(projectDir, messages) {
3521
+ const dir = path2.dirname(sessionPath(projectDir));
3522
+ fs2.mkdirSync(dir, { recursive: true });
3523
+ const data = {
3524
+ messages: messages.slice(-MAX_MESSAGES),
3525
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3526
+ projectHash: hashProject(projectDir)
3527
+ };
3528
+ fs2.writeFileSync(sessionPath(projectDir), JSON.stringify(data, null, 2), "utf-8");
3529
+ }
3530
+ function clearSession(projectDir) {
3531
+ const file = sessionPath(projectDir);
3532
+ if (fs2.existsSync(file))
3533
+ fs2.unlinkSync(file);
3534
+ }
3535
+ }
3536
+ });
3537
+
3538
+ // ../ai/dist/tools/response-cache.js
3539
+ var require_response_cache = __commonJS({
3540
+ "../ai/dist/tools/response-cache.js"(exports2) {
3541
+ "use strict";
3542
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
3543
+ if (k2 === void 0) k2 = k;
3544
+ var desc = Object.getOwnPropertyDescriptor(m, k);
3545
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
3546
+ desc = { enumerable: true, get: function() {
3547
+ return m[k];
3548
+ } };
3549
+ }
3550
+ Object.defineProperty(o, k2, desc);
3551
+ }) : (function(o, m, k, k2) {
3552
+ if (k2 === void 0) k2 = k;
3553
+ o[k2] = m[k];
3554
+ }));
3555
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
3556
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
3557
+ }) : function(o, v) {
3558
+ o["default"] = v;
3559
+ });
3560
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
3561
+ var ownKeys = function(o) {
3562
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
3563
+ var ar = [];
3564
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
3565
+ return ar;
3566
+ };
3567
+ return ownKeys(o);
3568
+ };
3569
+ return function(mod) {
3570
+ if (mod && mod.__esModule) return mod;
3571
+ var result = {};
3572
+ if (mod != null) {
3573
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
3574
+ }
3575
+ __setModuleDefault(result, mod);
3576
+ return result;
3577
+ };
3578
+ })();
3579
+ Object.defineProperty(exports2, "__esModule", { value: true });
3580
+ exports2.hashPrompt = hashPrompt;
3581
+ exports2.getCached = getCached2;
3582
+ exports2.setCache = setCache2;
3583
+ exports2.clearCache = clearCache;
3584
+ var fs2 = __importStar(require("fs"));
3585
+ var path2 = __importStar(require("path"));
3586
+ var crypto_1 = require("crypto");
3587
+ var CACHE_FILE = ".iacmp/cache.json";
3588
+ var TTL_MS = 7 * 24 * 60 * 60 * 1e3;
3589
+ function cachePath(projectDir) {
3590
+ return path2.join(projectDir, CACHE_FILE);
3591
+ }
3592
+ function loadCache(projectDir) {
3593
+ const file = cachePath(projectDir);
3594
+ if (!fs2.existsSync(file))
3595
+ return { entries: [] };
3596
+ try {
3597
+ return JSON.parse(fs2.readFileSync(file, "utf-8"));
3598
+ } catch {
3599
+ return { entries: [] };
3600
+ }
3601
+ }
3602
+ function saveCache(projectDir, data) {
3603
+ const dir = path2.dirname(cachePath(projectDir));
3604
+ fs2.mkdirSync(dir, { recursive: true });
3605
+ fs2.writeFileSync(cachePath(projectDir), JSON.stringify(data, null, 2), "utf-8");
3606
+ }
3607
+ function hashPrompt(prompt) {
3608
+ return (0, crypto_1.createHash)("sha256").update(prompt.trim()).digest("hex").slice(0, 16);
3609
+ }
3610
+ function getCached2(projectDir, prompt) {
3611
+ const hash = hashPrompt(prompt);
3612
+ const data = loadCache(projectDir);
3613
+ const entry = data.entries.find((e) => e.hash === hash);
3614
+ if (!entry)
3615
+ return null;
3616
+ const age = Date.now() - new Date(entry.createdAt).getTime();
3617
+ if (age > TTL_MS)
3618
+ return null;
3619
+ return entry.response;
3620
+ }
3621
+ function setCache2(projectDir, prompt, response) {
3622
+ const hash = hashPrompt(prompt);
3623
+ const data = loadCache(projectDir);
3624
+ data.entries = data.entries.filter((e) => e.hash !== hash);
3625
+ data.entries.push({
3626
+ hash,
3627
+ prompt: prompt.slice(0, 200),
3628
+ response,
3629
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
3630
+ });
3631
+ saveCache(projectDir, data);
3632
+ }
3633
+ function clearCache(projectDir) {
3634
+ const file = cachePath(projectDir);
3635
+ if (fs2.existsSync(file))
3636
+ fs2.unlinkSync(file);
3637
+ }
3638
+ }
3639
+ });
3640
+
3641
+ // ../ai/dist/index.js
3642
+ var require_dist = __commonJS({
3643
+ "../ai/dist/index.js"(exports2) {
3644
+ "use strict";
3645
+ Object.defineProperty(exports2, "__esModule", { value: true });
3646
+ exports2.buildIndexes = exports2.formatRetrievedContext = exports2.retrieve = exports2.bm25Search = exports2.buildBM25Index = exports2.Contextualizer = exports2.chunkKnowledgeFile = exports2.chunkIacmpDocs = exports2.chunkStackFile = exports2.clearCache = exports2.setCache = exports2.getCached = exports2.clearSession = exports2.saveSession = exports2.loadSession = exports2.invalidateIndexCache = exports2.readProjectContextAsync = exports2.readProjectContextRAG = exports2.readProjectMeta = exports2.readProjectContext = exports2.NATIVE_PROVIDERS = exports2.assertValidProvider = exports2.assertValidStackName = exports2.errMessage = exports2.isWithin = exports2.safeJoin = exports2.runSynth = exports2.renderAndConfirm = exports2.deleteFiles = exports2.writeGeneratedFiles = exports2.printStreamChunk = exports2.printNextSteps = exports2.printWarnings = exports2.printExplanation = exports2.stopThinking = exports2.printThinking = exports2.ChatSession = exports2.validateTypeScript = exports2.extractResponse = exports2.buildSystemPrompt = exports2.SYSTEM_PROMPT_TEMPLATE = exports2.SYSTEM_PROMPT = exports2.CopilotProvider = exports2.AnthropicProvider = void 0;
3647
+ var anthropic_1 = require_anthropic();
3648
+ Object.defineProperty(exports2, "AnthropicProvider", { enumerable: true, get: function() {
3649
+ return anthropic_1.AnthropicProvider;
3650
+ } });
3651
+ var copilot_1 = require_copilot();
3652
+ Object.defineProperty(exports2, "CopilotProvider", { enumerable: true, get: function() {
3653
+ return copilot_1.CopilotProvider;
3654
+ } });
3655
+ var system_prompt_1 = require_system_prompt();
3656
+ Object.defineProperty(exports2, "SYSTEM_PROMPT", { enumerable: true, get: function() {
3657
+ return system_prompt_1.SYSTEM_PROMPT;
3658
+ } });
3659
+ Object.defineProperty(exports2, "SYSTEM_PROMPT_TEMPLATE", { enumerable: true, get: function() {
3660
+ return system_prompt_1.SYSTEM_PROMPT_TEMPLATE;
3661
+ } });
3662
+ Object.defineProperty(exports2, "buildSystemPrompt", { enumerable: true, get: function() {
3663
+ return system_prompt_1.buildSystemPrompt;
3664
+ } });
3665
+ var code_extractor_1 = require_code_extractor();
3666
+ Object.defineProperty(exports2, "extractResponse", { enumerable: true, get: function() {
3667
+ return code_extractor_1.extractResponse;
3668
+ } });
3669
+ var validator_1 = require_validator();
3670
+ Object.defineProperty(exports2, "validateTypeScript", { enumerable: true, get: function() {
3671
+ return validator_1.validateTypeScript;
3672
+ } });
3673
+ var session_1 = require_session();
3674
+ Object.defineProperty(exports2, "ChatSession", { enumerable: true, get: function() {
3675
+ return session_1.ChatSession;
3676
+ } });
3677
+ var renderer_1 = require_renderer();
3678
+ Object.defineProperty(exports2, "printThinking", { enumerable: true, get: function() {
3679
+ return renderer_1.printThinking;
3680
+ } });
3681
+ Object.defineProperty(exports2, "stopThinking", { enumerable: true, get: function() {
3682
+ return renderer_1.stopThinking;
3683
+ } });
3684
+ Object.defineProperty(exports2, "printExplanation", { enumerable: true, get: function() {
3685
+ return renderer_1.printExplanation;
3686
+ } });
3687
+ Object.defineProperty(exports2, "printWarnings", { enumerable: true, get: function() {
3688
+ return renderer_1.printWarnings;
3689
+ } });
3690
+ Object.defineProperty(exports2, "printNextSteps", { enumerable: true, get: function() {
3691
+ return renderer_1.printNextSteps;
3692
+ } });
3693
+ Object.defineProperty(exports2, "printStreamChunk", { enumerable: true, get: function() {
3694
+ return renderer_1.printStreamChunk;
3695
+ } });
3696
+ var file_writer_1 = require_file_writer();
3697
+ Object.defineProperty(exports2, "writeGeneratedFiles", { enumerable: true, get: function() {
3698
+ return file_writer_1.writeGeneratedFiles;
3699
+ } });
3700
+ var file_deleter_1 = require_file_deleter();
3701
+ Object.defineProperty(exports2, "deleteFiles", { enumerable: true, get: function() {
3702
+ return file_deleter_1.deleteFiles;
3703
+ } });
3704
+ var diff_renderer_1 = require_diff_renderer();
3705
+ Object.defineProperty(exports2, "renderAndConfirm", { enumerable: true, get: function() {
3706
+ return diff_renderer_1.renderAndConfirm;
3707
+ } });
3708
+ var synth_runner_1 = require_synth_runner();
3709
+ Object.defineProperty(exports2, "runSynth", { enumerable: true, get: function() {
3710
+ return synth_runner_1.runSynth;
3711
+ } });
3712
+ var safe_path_1 = require_safe_path();
3713
+ Object.defineProperty(exports2, "safeJoin", { enumerable: true, get: function() {
3714
+ return safe_path_1.safeJoin;
3715
+ } });
3716
+ Object.defineProperty(exports2, "isWithin", { enumerable: true, get: function() {
3717
+ return safe_path_1.isWithin;
3718
+ } });
3719
+ Object.defineProperty(exports2, "errMessage", { enumerable: true, get: function() {
3720
+ return safe_path_1.errMessage;
3721
+ } });
3722
+ Object.defineProperty(exports2, "assertValidStackName", { enumerable: true, get: function() {
3723
+ return safe_path_1.assertValidStackName;
3724
+ } });
3725
+ Object.defineProperty(exports2, "assertValidProvider", { enumerable: true, get: function() {
3726
+ return safe_path_1.assertValidProvider;
3727
+ } });
3728
+ Object.defineProperty(exports2, "NATIVE_PROVIDERS", { enumerable: true, get: function() {
3729
+ return safe_path_1.NATIVE_PROVIDERS;
3730
+ } });
3731
+ var context_reader_1 = require_context_reader();
3732
+ Object.defineProperty(exports2, "readProjectContext", { enumerable: true, get: function() {
3733
+ return context_reader_1.readProjectContext;
3734
+ } });
3735
+ Object.defineProperty(exports2, "readProjectMeta", { enumerable: true, get: function() {
3736
+ return context_reader_1.readProjectMeta;
3737
+ } });
3738
+ Object.defineProperty(exports2, "readProjectContextRAG", { enumerable: true, get: function() {
3739
+ return context_reader_1.readProjectContextRAG;
3740
+ } });
3741
+ Object.defineProperty(exports2, "readProjectContextAsync", { enumerable: true, get: function() {
3742
+ return context_reader_1.readProjectContextRAG;
3743
+ } });
3744
+ Object.defineProperty(exports2, "invalidateIndexCache", { enumerable: true, get: function() {
3745
+ return context_reader_1.invalidateIndexCache;
3746
+ } });
3747
+ var session_store_1 = require_session_store();
3748
+ Object.defineProperty(exports2, "loadSession", { enumerable: true, get: function() {
3749
+ return session_store_1.loadSession;
3750
+ } });
3751
+ Object.defineProperty(exports2, "saveSession", { enumerable: true, get: function() {
3752
+ return session_store_1.saveSession;
3753
+ } });
3754
+ Object.defineProperty(exports2, "clearSession", { enumerable: true, get: function() {
3755
+ return session_store_1.clearSession;
3756
+ } });
3757
+ var response_cache_1 = require_response_cache();
3758
+ Object.defineProperty(exports2, "getCached", { enumerable: true, get: function() {
3759
+ return response_cache_1.getCached;
3760
+ } });
3761
+ Object.defineProperty(exports2, "setCache", { enumerable: true, get: function() {
3762
+ return response_cache_1.setCache;
3763
+ } });
3764
+ Object.defineProperty(exports2, "clearCache", { enumerable: true, get: function() {
3765
+ return response_cache_1.clearCache;
3766
+ } });
3767
+ var chunker_1 = require_chunker();
3768
+ Object.defineProperty(exports2, "chunkStackFile", { enumerable: true, get: function() {
3769
+ return chunker_1.chunkStackFile;
3770
+ } });
3771
+ Object.defineProperty(exports2, "chunkIacmpDocs", { enumerable: true, get: function() {
3772
+ return chunker_1.chunkIacmpDocs;
3773
+ } });
3774
+ Object.defineProperty(exports2, "chunkKnowledgeFile", { enumerable: true, get: function() {
3775
+ return chunker_1.chunkKnowledgeFile;
3776
+ } });
3777
+ var contextualizer_1 = require_contextualizer();
3778
+ Object.defineProperty(exports2, "Contextualizer", { enumerable: true, get: function() {
3779
+ return contextualizer_1.Contextualizer;
3780
+ } });
3781
+ var bm25_1 = require_bm25();
3782
+ Object.defineProperty(exports2, "buildBM25Index", { enumerable: true, get: function() {
3783
+ return bm25_1.buildBM25Index;
3784
+ } });
3785
+ Object.defineProperty(exports2, "bm25Search", { enumerable: true, get: function() {
3786
+ return bm25_1.bm25Search;
3787
+ } });
3788
+ var retriever_1 = require_retriever();
3789
+ Object.defineProperty(exports2, "retrieve", { enumerable: true, get: function() {
3790
+ return retriever_1.retrieve;
3791
+ } });
3792
+ Object.defineProperty(exports2, "formatRetrievedContext", { enumerable: true, get: function() {
3793
+ return retriever_1.formatRetrievedContext;
3794
+ } });
3795
+ var indexer_1 = require_indexer();
3796
+ Object.defineProperty(exports2, "buildIndexes", { enumerable: true, get: function() {
3797
+ return indexer_1.buildIndexes;
3798
+ } });
3799
+ }
3800
+ });
3801
+
3802
+ // src/commands/ai.ts
3803
+ var ai_exports = {};
3804
+ __export(ai_exports, {
3805
+ default: () => AI
3806
+ });
3807
+ module.exports = __toCommonJS(ai_exports);
3808
+ var import_core = require("@oclif/core");
3809
+ var fs = __toESM(require("fs"));
3810
+ var path = __toESM(require("path"));
3811
+ var cp = __toESM(require("child_process"));
3812
+ var import_chalk = __toESM(require("chalk"));
3813
+ var import_ora = __toESM(require("ora"));
3814
+ var import_ai = __toESM(require_dist());
3815
+ function resolveAIProvider() {
3816
+ if (process.env["ANTHROPIC_API_KEY"]) {
3817
+ return new import_ai.AnthropicProvider(process.env["ANTHROPIC_API_KEY"]);
3818
+ }
3819
+ if (process.env["GITHUB_TOKEN"]) {
3820
+ return new import_ai.CopilotProvider(process.env["GITHUB_TOKEN"]);
3821
+ }
3822
+ throw new Error(
3823
+ "Configure ANTHROPIC_API_KEY no .env do projeto\n ANTHROPIC_API_KEY=sk-ant-..."
3824
+ );
3825
+ }
3826
+ function resolveIaCProvider(flags, cwd) {
3827
+ if (flags.provider) return flags.provider;
3828
+ const configPath = path.join(cwd, "iacmp.json");
3829
+ if (fs.existsSync(configPath)) {
3830
+ try {
3831
+ const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
3832
+ if (typeof config["provider"] === "string") return config["provider"];
3833
+ } catch {
3834
+ }
3835
+ }
3836
+ return "aws";
3837
+ }
3838
+ function createDirectAsk() {
3839
+ const readline = require("readline");
3840
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
3841
+ return (question) => new Promise((resolve2) => {
3842
+ rl.question(question, (answer) => {
3843
+ rl.close();
3844
+ resolve2(answer.trim());
3845
+ });
3846
+ });
3847
+ }
3848
+ function createContextualProvider(base, projectContext) {
3849
+ const systemPrompt = (0, import_ai.buildSystemPrompt)(projectContext);
3850
+ return {
3851
+ name: base.name,
3852
+ async chat(messages) {
3853
+ return base.chat([{ role: "system", content: systemPrompt }, ...messages]);
3854
+ },
3855
+ async stream(messages, onChunk) {
3856
+ return base.stream([{ role: "system", content: systemPrompt }, ...messages], onChunk);
3857
+ }
3858
+ };
3859
+ }
3860
+ async function runGeneration(provider, session, cwd, dryRun, iacProvider, ask, lastUserPrompt) {
3861
+ const cached = (0, import_ai.getCached)(cwd, lastUserPrompt);
3862
+ let raw = "";
3863
+ let fromCache = false;
3864
+ if (cached) {
3865
+ try {
3866
+ (0, import_ai.extractResponse)(cached);
3867
+ console.log(import_chalk.default.dim(" \u21A9 resposta do cache"));
3868
+ raw = cached;
3869
+ fromCache = true;
3870
+ session.addAssistantMessage(raw);
3871
+ } catch {
3872
+ raw = "";
3873
+ }
3874
+ }
3875
+ if (!raw) {
3876
+ const spinner = (0, import_ora.default)({ text: "Gerando...", spinner: "dots" }).start();
3877
+ const chunks = [];
3878
+ try {
3879
+ await provider.stream(session.getMessages(), (chunk) => chunks.push(chunk));
3880
+ } catch (err) {
3881
+ spinner.fail("Erro ao chamar a IA: " + err.message);
3882
+ return null;
3883
+ }
3884
+ spinner.succeed("Resposta recebida");
3885
+ raw = chunks.join("");
3886
+ session.addAssistantMessage(raw);
3887
+ }
3888
+ let parsed;
3889
+ try {
3890
+ parsed = (0, import_ai.extractResponse)(raw);
3891
+ } catch {
3892
+ console.log("\n" + raw.trim() + "\n");
3893
+ return null;
3894
+ }
3895
+ if (!fromCache) {
3896
+ (0, import_ai.setCache)(cwd, lastUserPrompt, raw);
3897
+ }
3898
+ const tsFiles = parsed.files.filter((f) => f.path.endsWith(".ts"));
3899
+ if (tsFiles.length > 0) {
3900
+ const result = (0, import_ai.validateTypeScript)(tsFiles, cwd);
3901
+ if (!result.valid) {
3902
+ const spinner = (0, import_ora.default)({ text: "Valida\xE7\xE3o TypeScript falhou \u2014 corrigindo...", spinner: "dots" }).start();
3903
+ session.addUserMessage(`Erros TypeScript:
3904
+ ${result.errors.join("\n")}
3905
+
3906
+ Corrija e retorne o JSON completo.`);
3907
+ const retryChunks = [];
3908
+ try {
3909
+ await provider.stream(session.getMessages(), (chunk) => retryChunks.push(chunk));
3910
+ spinner.succeed("C\xF3digo corrigido");
3911
+ const retryRaw = retryChunks.join("");
3912
+ session.addAssistantMessage(retryRaw);
3913
+ try {
3914
+ parsed = (0, import_ai.extractResponse)(retryRaw);
3915
+ } catch {
3916
+ }
3917
+ } catch (err) {
3918
+ spinner.fail("Erro no retry: " + err.message);
3919
+ }
3920
+ }
3921
+ }
3922
+ (0, import_ai.printExplanation)(parsed.explanation);
3923
+ (0, import_ai.printWarnings)(parsed.warnings);
3924
+ if (parsed.files.length > 0) {
3925
+ await (0, import_ai.writeGeneratedFiles)(parsed.files, cwd, dryRun, ask);
3926
+ }
3927
+ (0, import_ai.printNextSteps)(parsed.nextSteps);
3928
+ if (!dryRun && parsed.files.length > 0) {
3929
+ const answer = await ask("Quer rodar `iacmp synth` agora? (y/n) ");
3930
+ if (answer === "y") (0, import_ai.runSynth)(cwd, iacProvider);
3931
+ }
3932
+ return parsed;
3933
+ }
3934
+ var AI = class _AI extends import_core.Command {
3935
+ static description = "Gera stacks de infraestrutura via IA (Claude ou GitHub Copilot)";
3936
+ static args = {
3937
+ prompt: import_core.Args.string({ description: "Descri\xE7\xE3o do que criar (obrigat\xF3rio sem --chat)", required: false })
3938
+ };
3939
+ static flags = {
3940
+ chat: import_core.Flags.boolean({ description: "Modo chat interativo", default: false }),
3941
+ "dry-run": import_core.Flags.boolean({ description: "Gera e exibe sem salvar arquivos", default: false }),
3942
+ provider: import_core.Flags.string({ char: "p", description: "Provider alvo (aws, azure, gcp, terraform)" })
3943
+ };
3944
+ static examples = [
3945
+ '$ iacmp ai "cria uma Lambda com API Gateway"',
3946
+ "$ iacmp ai --chat",
3947
+ '$ iacmp ai --dry-run "cria uma VPC com subnets"',
3948
+ '$ iacmp ai "migra a stack para azure" --provider azure'
3949
+ ];
3950
+ async run() {
3951
+ const { args, flags } = await this.parse(_AI);
3952
+ const cwd = process.cwd();
3953
+ const dryRun = flags["dry-run"];
3954
+ const iacProvider = resolveIaCProvider({ provider: flags.provider }, cwd);
3955
+ if (flags.chat) {
3956
+ const chatScript = path.resolve(__dirname, "../../bin/chat.js");
3957
+ const child = cp.spawn(process.execPath, [chatScript], {
3958
+ stdio: "inherit",
3959
+ env: {
3960
+ ...process.env,
3961
+ IACMP_CWD: cwd,
3962
+ IACMP_PROVIDER: iacProvider,
3963
+ IACMP_DRYRUN: dryRun ? "1" : "0"
3964
+ }
3965
+ });
3966
+ await new Promise((resolve2) => child.on("close", resolve2));
3967
+ return;
3968
+ }
3969
+ if (!args.prompt) {
3970
+ this.error('Informe o prompt ou use --chat para modo interativo.\nExemplo: iacmp ai "cria uma Lambda com API Gateway"');
3971
+ }
3972
+ let aiProvider;
3973
+ try {
3974
+ aiProvider = resolveAIProvider();
3975
+ } catch (err) {
3976
+ this.error(err.message);
3977
+ }
3978
+ const session = new import_ai.ChatSession();
3979
+ const ask = createDirectAsk();
3980
+ const projectContext = (0, import_ai.readProjectContext)(cwd);
3981
+ const provider = createContextualProvider(aiProvider, projectContext);
3982
+ session.addUserMessage(args.prompt);
3983
+ await runGeneration(provider, session, cwd, dryRun, iacProvider, ask, args.prompt);
3984
+ }
3985
+ };